Realistic FPS Prefab Support

This page describes how to set up the Dialogue System with Azuline Studios' Realistic FPS Prefab.

Realistic FPS Prefab copyright © Azuline Studios.

Realistic FPS Prefab Setup

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 Assets ► Pixel Crushers ► Dialogue System ► Third Party Support ► Realistic FPS Prefab Support.
  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., from Prefabs) to your scene.
  2. Add an RFPS player prefab if one isn't already in the scene.
  3. Select menu item Tools → Pixel Crushers → 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.
    • It will also add an FPS Lua Bridge to FPS Player that syncs RFPS and the Dialogue System as described in How to Disable Player Control During Conversations.
    • It may also ask if you want to add a Selector for the Dialogue System's interaction system. If you want to use RFPS interaction instead, you can answer No.
    • If you want to add a hotkey to open/close the quest log window, add an FPS Quest Log Window Hotkey component to FPS Player.
  4. Set up NPCs as normal for the Dialogue System. Use a Dialogue System Events component to disable the NPCAttack component during conversations, as described in How to Control NPC AI During Conversations.
  5. Set up miscellaneous triggers with the Dialogue System On Pick Up Item script if you want to tie them into RFPS's pickup/interaction system.

Controlling the Dialogue System

How to Disable Player Control During Conversations

The Disable Gameplay In Conversations menu items in Realistic FPS Prefab Setup Part 2 adds components to the player that disable player control during conversations.

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;
    }
  2. 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.
    A static class that provides a simplified interface to the Dialogue System's core functions.
    Definition DialogueManager.cs:14
    static void StopConversation()
    Stop the current conversation immediately, and sends an OnConversationEnd message to the actor and co...
    Definition DialogueManager.cs:583
    Definition DemoInputRegistration.cs:4
    Definition MessageEventsEditor.cs:7

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 give the boss a Dialogue System Trigger set to On Conversation End that checks a condition and activates the son.
  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.

  1. Add a Position Saver component to save the NPC's position in saved games.
  2. 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.)
  3. 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();
  4. RFPS's CharacterDamage script will now have an OnDie() event. Click the "+" to add a new entry, and assign PersistentDeadBody.OnDestroy.
  5. Add an UnregisterNPCOnDestroy component. (Skip if your scene doesn't have an NPCRegistry.)
  6. 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.

Saving and Loading Games

You can use the Save System to save without having to write any scripts.

If you want saved games to record the state of objects in the game, you must add persistent data components such as Position Saver and Destructible Saver. 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.

Using Multiple Scenes

To use multiple scenes:

  • 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.

FPS Lua Bridge

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 a Dialogue Actor 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 a Quest Trigger component (although the newer equivalent is Dialogue System Trigger) to start the quest. Each zombie's OnDie() event invokes a Dialogue System Trigger that increments the kill counter and then invokes another Dialogue System Trigger that checks the status of the quest.

Don't use Increment On Destroy with RFPS NPCs because they don't disappear right away. Their dead rigidbodies remain active for several seconds.


<< Third Party Integration