Best Practice to Instantiate NPC

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
User avatar
DearDeerDee
Posts: 30
Joined: Mon Mar 22, 2021 10:00 am

Best Practice to Instantiate NPC

Post by DearDeerDee »

Hello, I'm working on a bus simulator.

What I Want:
The player talks to someone at a station, and then chooses the passengers he wants to carry. Then after the player returns to the bus, he can see the passengers he just chose sitting on the chairs. The player can even interact and talk with the passengers.

Current Issue
How to store the passengers the player has chosen?

The station and bus interior are two scenes, How to pass the data from one scene to another? I know I can use variables, but in the case of my game, it would be a mess to rely on variable.

How to instantiate the passengers in the bus interior scene?
User avatar
Tony Li
Posts: 22047
Joined: Thu Jul 18, 2013 1:27 pm

Re: Best Practice to Instantiate NPC

Post by Tony Li »

Hi,

Let's look at the bus scene first. In the bus scene, what would be a good way to know which passengers to instantiate, and then to instantiate them? Here's one idea:

1. Put each passenger prefab in a Resources folder. (Or Addressables or asset bundle, or whatever. I'll use Resources because it makes the code simpler to read here. I'll also make a few other decisions below that make the code shorter.) So your Resources folder might contain prefabs named Ann, Bob, Carl, Donna, etc.

2. Add a script to the Dialogue Manager GameObject that maintains a list of passengers to instantiate. Example:

Code: Select all

public class PassengerManifest : MonoBehaviour
{
    public List<string> passengerNames = new List<string>();
}
3. In the bus scene, add a script that instantiates the passengers:

Code: Select all

public class Bus : MonoBehaviour
{
    public List<Transform> seats; //<-- Assume these are assigned in the inspector.
    
    private void Start()
    {
        var passengerManifest = FindObjectOfType<PassengerManifest>();
        for (int i = i; i < passengerManifest.passengerNames.Count; i++)
        {
            GameObject prefab = Resources.Load<GameObject>(passengerManifest.passengerNames[i]);
            Instantiate(prefab, seats[i]);
        }
    }
}
In the station scene, you'll want to populate the PassengerManifest's passengerNames list. One way to do this is to add a C# method:

Code: Select all

public class PassengerManifest : MonoBehaviour
{
    public List<string> passengerNames = new List<string>();
    
    public void AddPassenger(string passengerName)
    {
        passengerNames.Add(passengerName);
    }
}
Since you'll want to call the AddPassenger() method in the station's conversation, register it with Lua:

Code: Select all

public class PassengerManifest : MonoBehaviour
{
    public List<string> passengerNames = new List<string>();
    
    private void Awake()
    {
        Lua.RegisterFunction("AddPassenger", this, SymbolExtensions.GetMethodInfo(() => AddPassenger(string.Empty)));
    }
    
    public void AddPassenger(string passengerName)
    {
        passengerNames.Add(passengerName);
    }
}
Then in your dialogue entries' Script fields, call AddPassenger:
  • Dialogue Text: "Hi! I'm Bob. Here's my bus ticket."
  • Script: AddPassenger("Bob")
If you want to avoid having to type "AddPassenger" in every Script field, set up a Custom Lua Function Info asset.
User avatar
DearDeerDee
Posts: 30
Joined: Mon Mar 22, 2021 10:00 am

Re: Best Practice to Instantiate NPC

Post by DearDeerDee »

Hi Tony, thanks for your response! It is super informative!
User avatar
Tony Li
Posts: 22047
Joined: Thu Jul 18, 2013 1:27 pm

Re: Best Practice to Instantiate NPC

Post by Tony Li »

Glad to help!
Post Reply