Realistic FPS Prefab

(Click Here for Video Tutorial)

This page describes how to set up the Dialogue System with Azuline Studios' Realistic FPS Prefab. (Realistic FPS Prefab v1.23+ is required.)

Realistic FPS Prefab copyright © Azuline Studios.

There is a separate page for Realistic FPS Prefab / S-Inventory integration. You should familiarize yourself with the basics of S-Inventory integration before reading the Realistic FPS Prefab / S-Inventory page.


Realistic FPS Prefab Setup

Special Step for RFPS 1.2

If you're using RFPS 1.2 (and not RFPS 1.4+), select Edit > Project Settings > Player. To the Inspector's Scripting Define Symbols field, add RFPS_1_2. If this field already contains symbols, separate them with a semicolon ( ; ).

Realistic FPS Prefab Setup Part 1

  1. To use the Dialogue System with Realistic FPS Prefab, import the package Third Party Support/Realistic FPS Prefab Support. This will unpack files into the folder Third Party Support/Realistic FPS Prefab.
  2. Realistic FPS Prefab is a complete project asset. This means it overwrites Unity's default input settings. Other assets, such as the Dialogue System, use the Unity default inputs Horizontal and Vertical that aren't present in Realistic FPS Prefab's custom input settings. Before using the Dialogue System, you must re-add these inputs. Select Edit > Project Settings > Input. Then add these four entries:

At this point you can jump to the Example Scenes if you'd like to get a preview of how the integration works before continuing to set up your own scene.

Realistic FPS Prefab Setup Part 2

Once you've imported the packages and fixed the Input Manager, follow these steps to set up your scene:

  1. Add a Dialogue Manager GameObject (e.g., drag the Dialogue Manager prefab from the Prefabs folder into your scene). Then:
  2. Optional: If you've manually created your Dialogue Manager, set Display Settings > Camera Settings > Default Sequence to Delay({{end}}) to delay without moving the camera. (The default Dialogue Manager prefab is already configured this way.) Since the player doesn't have a body, it doesn't make sense to move the camera into a closeup on the conversation participants.
  3. Optional: If you've manually created your Dialogue Manager, you may want to add a Quest Log Window.
  4. Optional: If you want to use the Dialogue System's interaction system, select the FPS Camera > Main Camera GameObject. Then select Component > Dialogue System > Actor > Player > Selector. This will add a selector that you can use to interact with Dialogue System usable objects. If you plan to use RFPS's interaction system instead, skip this step.
    • If you want to be able to interact with NPCs, set the Layer Mask to "Default, NPCs".
    • Set Use Key to a key not reserved by RFPS, such as "N", or KeyCode.None if you don't want to assign a key.
    • Set the Use Button to a button defined in the Unity input manager. (Note: RFPS's input settings don't define Fire2.)
    • Change the Default Use Message to reflect your key/button choices.
  5. Select your FPS Main GameObject or the FPS Player child GameObject. Then select Component > Dialogue System > Third Party > Realistic FPS Prefab > Disable Gameplay In Conversations. This will add components to FPS Player to make it work smoothly with the Dialogue System, as described in How to Disable Player Control During Conversations.
    1. It will also add an FPS Lua Bridge to FPS Player (or do it manually with Component > Dialogue System > Third Party > Realistic FPS Prefab > FPS Lua Bridge). This component syncs RFPS and the Dialogue System, as described in How to Disable Player Control During Conversations.
  6. Set up NPCs as normal for the Dialogue System. Use the Set Enabled On Dialogue Event component to disable the NPCAttack component during conversations, as described in How to Control NPC AI During Conversations.
  7. Set up miscellaneous triggers with the DialogueSystemOnPickUpItem script if you want to tie them into RFPS's pickup system.

Using Unity UI

You may be interested in using Unity UI to show HUD elements such as ammo text. Here are unofficial instructions: http://www.pixelcrushers.com/how-to-use-unity-ui-for-ammo-text-in-realistic-fps-prefab/


Controlling the Dialogue System

How to Disable Player Control During Conversations

During conversations, you will usually want to disable player movement and camera control. To do this, select the player prefab. Then select Component > Dialogue System > Third Party > Realistic FPS Prefab > Disable Player On Conversation. (Note that if you plan to use the Dialogue System's selector/usable system, add a Selector component to the Main Camera GameObject first.

The Disable Player On Conversation menu item will add and configure Set Active On Dialogue Event and Set Enabled On Dialogue Event components. These components will deactivate Realistic FPS Prefab components when the player starts a conversation, and reactivate them when the conversation ends.

Additional Notes About RFPS Player During Conversations

If you want to control the camera during conversations and cutscene sequences, control the FPSPlayer GameObject. The camera and visible body will follow it as described below:

Visible Body

If your player uses a visible body, the integration will also configure the player to disable the Visible Body component and play the idle animation when a conversation starts. The body will follow the FPSPlayer's position at the offset it has when the conversation starts.

Camera Kick

The integration will disable the Camera Kick component during conversations. The camera will follow the FPSPlayer's position at the offset it has when the conversation starts.

How to Control NPC AI During Conversations

How to Disable NPC AI During Conversations

During conversations, you will usually want to disable NPC AI on the NPC that the player is talking to. Otherwise the NPC could wander away or get into a fight while the player is trying to converse.

To do this, add a Pause AI On Conversation component to the NPC.

Note that other NPCs are not paused. This only applies to the NPC involved in the conversation. You may want to make sure this NPC is placed away from danger so enemies don't interrupt the conversation.

How to Stop Conversations if NPC is Hurt

To make an NPC break off conversation if it gets hurt, you must edit the Realistic FPS Prefab script CharacterDamage.cs. Make these two changes:

  1. At line 26, insert these lines:
private bool isInConversation = false;
public void OnConversationStart(Transform actor)
{
isInConversation = true;
}
public void OnConversationEnd(Transform actor)
{
isInConversation = false;
}
  1. In the ApplyDamage method, add the line shown below:
public void ApplyDamage ( float damage, Vector3 attackDir, Vector3 attackerPos, Transform attacker, bool isPlayer ){
if (isInConversation) PixelCrushers.DialogueSystem.DialogueManager.StopConversation(); //<-- ADD THIS LINE.

How to Activate NPCs During Conversations

At some point, you may want to activate another NPC during a conversation. For example, in a conversation with a mob boss, the player accepts a quest to escort the boss's son from jail to home. The son GameObject was previously inactive. If you use the SetActive() sequencer command, the son's AI component will fail to initialize. This is because it looks for certain active RFPS components on the player GameObject. But these components are inactive during conversations. Here are two solutions to this issue:

  1. Don't activate the son GameObject until the conversation ends. You can use the Set Active On Dialogue Event component to do this. Set its trigger to OnConversation, and set the son GameObject active in the component's On End section if a condition is true.
  2. Or keep the son GameObject active at the start of the scene, and deactivate it after one frame. This gives the AI component time to find the player's RFPS components before being deactivated.

How to Keep NPCs Dead

Use these steps to make NPCs' positions and living/dead states persistent.

  • Add a Persistent Position Data component to save the NPC's position in saved games.
  • Add a PersistentDeadBody component. Assign a unique variable name to record that this NPC is dead. (Don't use PersistentDestructible. Use RFPS Support > PersistentDeadBody instead.)
  • Edit RFPS's CharacterDamage.cs script in two places.

On line 7 (after public class CharacterDamage : MonoBehaviour {) add:

public UnityEngine.Events.UnityEvent onDie;

On line ~180, change this section of the ApplyDamage method from:

//Kill NPC
if (hitPoints <= 0.0f){
AIComponent.vocalFx.Stop();

to:

//Kill NPC
if (hitPoints <= 0.0f){
onDie.Invoke(); // ADD THIS LINE!
AIComponent.vocalFx.Stop();
  • RFPS's CharacterDamage script will now have an OnDie() event. Click the "+" to add a new entry, and assign PersistentDeadBody.OnDestroy.
  • Add an UnregisterNPCOnDestroy component. (Skip if your scene doesn't have an NPCRegistry.)
  • Assign a corpse prefab to CharacterDamage's Dead Replacement field. If you don't have a corpse replacement, you can make one by copying your regular NPC prefab and removing all the RFPS-specific scripts, including the LocationDamage scripts on child GameObjects.

Dialogue System On Pick Up Item

The Dialogue System On Pick Up Item script can be attached to any Pickup object. (When configuring Pickup objects, remember to set the tag to Usable and the layer to Ragdoll/Pickups.)

When the player picks up the object, this script will perform various actions. You can use it to advance quests, show gameplay alerts, run Lua code, play sequences, and send messages (for example, send an "OnUse" message to a traditional Dialogue System trigger). If you want to remove the object from the scene when it's picked up, tick Destroy.

If you configure this component to send "OnUse" to its own GameObject, you can cleanly integrate RFPS's interaction system with the Dialogue System's trigger system. For example, you can add a Conversation Trigger to a GameObject and set the trigger event to "OnUse". Then add a Dialogue System On Pick Up Item to the same GameObject and configure it to send "OnUse" to itself.

Lua On Pick Up Item

(This component has been deprecated by the more full-featured Dialogue System On Pick Up Item component described above.)

The Lua On Pick Up Item script can be attached to any Pickup object. When the player picks up the object, this script will run a Lua command. In the example scene, the Shotgun Pickup uses this script to display a gameplay alert message.

Lua On Destroy

The Lua On Destroy script can be attached to any object. When the object is destroyed, the script will run Lua code. You can add this to an enemy to update the kill count when the enemy is destroyed. An alternative is the Increment On Destroy component.

Saving and Loading Games

For examples of saving and loading games, refer to the Multiple Scene Example.

You can use the Game Saver component to save without having to write any scripts, as demonstrated in the Main Menu Scene.

You can also save and load in script, as demonstrated in the Gameplay Scenes.

If you use PlayMaker, you can use PlayMaker's Save & Load Actions. To save, use the Record Savegame Data to record the current state of the game in a string. Then save this string however you want. To reload the saved game, retrieve this string and send it to the Apply Savegame Data action.

If you want saved games to record the state of objects in the game, you must add persistent data components such as Persistent Position Data and Persistent Destructible. See the Save System documentation for more details.

To record the player's position and rotation, inspect the FPS Lua Bridge on FPS Player and tick Save Position.


How to Disable Player Control During Conversations

The FPS Lua Bridge synchronizes data between the Realistic FPS Prefab player and the Dialogue System's Lua environment. It automatically synchronizes before and after conversations, and you can synchronize manually using SyncFPSToLua() and SyncLuaToFPS(). It also registers some Lua functions that you can use in conversations, conditions, and Lua Triggers.

The bridge uses the following values in the Lua environment:

Lua value Description
Actor["Player"].hitPoints Current hit points
Actor["Player"].maximumHitPoints Maximum hit points
Actor["Player"].hungerPoints Current hunger points
Actor["Player"].thirstPoints Current thirst points
Actor["Player"].invulnerable Current invulnerability state (true or false)
Actor["Player"].currentWeaponIndex Index of currently-equipped weapon (0=unarmed, 1=knife, etc.)
Variable["(weaponname)"] A Boolean (true or false) indicating whether the player has the named weapon
Variable["(weaponname)_Ammo"] An integer indicating how much ammo the player has for the named weapon

Additional Notes About RFPS Player During Conversations

  • The player's Actor Name defaults to "Player", but you can change it if the name of your player actor is different in your dialogue database. To do this, add an Override Actor Name component.
  • If the player name or any weapon names have spaces or hyphens, those characters will be replaced with underscores (_) in Lua.

Examples

To check if the player has a shotgun:

Variable["Shotgun"] == true

To take the shotgun away from the player:

Variable["Shotgun"] = false

To completely heal the player:

Actor["Player"].hitPoints = Actor["Player"].maximumHitPoints

HUD

The bridge also hides the HUD during conversations if you tick Hide Hud In Conversations.

Sync Lua To FPS On Load Level

Add the Sync Lua To FPS On Load Level component to the Dialogue Manager if the player will move between scenes, including appearing in a gameplay scene from a menu scene.

Lua Functions

The bridge adds these four Lua functions:

GetRfpsFaction(subject)

Given a subject name (a string that matches a GameObject name in the scene), this function returns a number indicating the subject's faction:

Value Faction
1 Friendly to player
2 Hostile to player (Alien)
3 Hostile to all other factions (Zombie)

If no GameObject matches the subject name, this function returns 1.

Example: You can set a dialogue entry's Conditions field to the value below to only use that entry if "Sad Robot" is friendly:

GetRfpsFaction("Sad Robot") == 1

SetRfpsFaction(subject, faction)

Given a subject name (a string that matches a GameObject name in the scene), sets the subject's faction. The faction values are listed in the table above. Example: You can set a dialogue entry's Script field to the value below to make "Sad Robot" hostile:

SetRfpsFaction("Sad Robot", 2)

Example Scenes

Realistic FPS Prefab Example

Sad Robot Conversation

The "Sad Robot" conversation runs a quest to get a shotgun for the sad robot. It manages the quest, and also checks whether Variable["Shotgun"] == true. If it's true, it offers the player the option of giving the shotgun to the sad robot. If the player gives the shotgun to the sad robot, the conversation runs the script Variable["Shotgun"] = false to remove the shotgun from the player's inventory.

After giving the sad robot a shotgun, you can choose a dialogue entry that changes its faction to aggressive. This uses the SetRfpsFaction() Lua function.

Happy Robot Conversation

The "Happy Robot" conversation tests giving and taking weapons and ammo, and reporting health.

Kill Zombies Quest

If you enter the back of the house, you'll trigger the "Kill 4 Zombies" quest. This uses the Quest Trigger component to start the quest and Increment On Destroy on each house zombie to increment the kill counter. Another Quest Trigger outside each door of the house checks the status of the quest.

You may notice two quirks:

  1. The zombie kill count sometimes increases on its own. This is because the RFPS MonsterTrigger doesn't play nicely with components such as Increment On Destroy that listen for OnDestroy() messages.
  2. When you reload a level (including when you die and respawn), all zombies in the old level are destroyed, triggering the Lua On Destroy events that increment the kill count. To prevent this in your own project, call PersistentDataManager.LevelWillBeUnloaded() before loading or reloading a level. This tells components such as Lua On Destroy to ignore the OnDestroy message that's generated when an old level is unloaded.

Multiple Scene Example

The integration package doesn't include a multiple scene example any more (to keep the package reasonably small), but it's fairly easy to set up multiple scenes. In brief, the steps are:

  • Add a Dialogue Manager to your start scene.
  • Add a Level Manager component to the Dialogue Manager if it doesn't already have one.
  • Add a Sync Lua To FPS On Load Level component to the Dialogue Manager if it doesn't already have one.
  • In each gameplay scene, add a player fully configured with Dialogue System components.
    • Inspect the FPS Player's FPS Lua Bridge component, and tick Save Position.
  • Your gameplay scenes don't have to contain a Dialogue Manager GameObject. The Dialogue Manager GameObject persists from the start scene. But for easy testing you can still add a Dialogue Manager to each gameplay scene so you can play the scene without having to come in from the start scene. Just remember that it will be destroyed by the start scene's Dialogue Manager when you're playing from the start scene.

<< Third Party Support

PixelCrushers.DialogueSystem.DialogueTriggerEvent.OnConversationEnd
Trigger when the GameObject receives an OnConversationEnd message
PixelCrushers.DialogueSystem.DialogueManager.StopConversation
static void StopConversation()
Stop the current conversation immediately, and sends an OnConversationEnd message to the actor and co...
Definition: DialogueManager.cs:458
PixelCrushers.DialogueSystem.DialogueManager
A static class that provides a simplified interface to the dialogue system's core functions.
Definition: DialogueManager.cs:10
PixelCrushers.DialogueSystem
Definition: ArticyConverterWindow.cs:8
PixelCrushers
Definition: ArticyConverterWindow.cs:8