Hi, I am facing a situation that, in many scenes, different playable characters will be used, so Allowing Player Switching seems to be a good option. However, the playable characters would have different custom settings and components in different scenes. So the most convenient way for me is to have the game objects of playable characters in the scene, and switch to the character to play when needed.
But using the Allowing Player Switching function would instantiate the prefab of character game object even an instance of the prefab is already in the scene. Is there a way to ask AC to just use the prefab instance that is already in the scene?
I have also tried to switch off Allowing Player Switching, and then turn on and off the playable character game objects in the beginning of the scene using script or actionlist. But it doesn't work because AC is "too fast" and decide using the lowest Player object in the hierarchy before I can turn them off.
I am using AC 1.72.47 and Unity 2019.4.6f1
Is there a way I can achieve the desired effect? Thank you very much for your help.
It looks like you're new here. If you want to get involved, click one of these buttons!
Comments
When using Player-switching, AC takes control over exactly where the assigned Players are at all times - local Player objects in the scene aren't compatible with this feature. If you rely on Player-switching, you'll need to remove the local Players from your scenes.
Depending on the complexity of the settings/components involved, from what you've described I'd say the two main possible approaches would be:
Thank you for the ideas. Option 1 seems to be more convenient for me. May I ask would there be a limit or performance concern for a large number of player prefabs in the Character Settings?
Or otherwise, would there be a way to achieve the effect with Not allowing player switching?
Sorry for multiple posts, but to elaborate the question in the previous post, I mean would switching the game objects active and inactive at OnCompleteScenePreload, OnAwaitSceneActivation, OnInitialiseScene, or OnAfterChangeScene, etc. be fast enough for AC to use only the remaining active Player object?
There's no forced limit, and the performance of AC "tracking" characters should be minimal. Any performance considerations would revolve around the size of the assets involved, since they'd be referenced by the Settings Manager and thus referenced by the project on startup.
The intention being to force a particular character as the active Player? It shouldn't come down to having to "beat" AC to disable objects like that. The Player character can be assigned through script:
Any other Player characters in the scene should then behave like NPCs. This manual-assignment won't be recorded in save-games, however, so you'd need to keep track separately of what Player object is currently active, and assign them as above after loading a save-file.
I have tried using
AC.KickStarter.player = myNewPlayer;
but I run into a problem. It happens both with or without Player Switching allowed:What I did is:
Use the code:
public AC.player myNewPlayer;
public void AssignPlayer() {
AC.KickStarter.player = myNewPlayer;
}
Assign the Player game object to
myNewPlayer
in Unity editor.AssignPlayer()
in the OnStart actionlist using Object > Call Event.Then I got the error:
NullReferenceException: Object reference not set to an instance of an object
AC.MainCamera.LoadData (AC.PlayerData playerData, System.Boolean snapCamera) (at Assets/Plugins/AdventureCreator/Scripts/Camera/MainCamera.cs:1634)
AC.KickStarter.set_player (AC.Player value) (at Assets/Plugins/AdventureCreator/Scripts/Game engine/KickStarter.cs:1004)
s03BigHouseLobby_ScriptedFunctions.AssignPlayer () (at Assets/Ricky/Scripts/Script Function Objects/s03BigHouseLobby_ScriptedFunctions.cs:12)
UnityEngine.Events.InvokableCall.Invoke () (at :0)
UnityEngine.Events.UnityEvent.Invoke () (at :0)
AC.ActionEvent.Run () (at Assets/Plugins/AdventureCreator/Scripts/Actions/ActionEvent.cs:44)
AC.ActionList+d__34.MoveNext () (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:374)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at :0)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
AC.ActionList:ProcessAction(Int32) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:327)
AC.ActionList:ProcessActionEnd(ActionEnd, Int32, Boolean) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:557)
AC.ActionList:EndAction(Action) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:475)
AC.d__34:MoveNext() (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:443)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
AC.ActionList:ProcessAction(Int32) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:327)
AC.ActionList:BeginActionList(Int32, Boolean) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:294)
AC.ActionList:Interact(Int32, Boolean) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:195)
AC.ActionList:Interact() (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:158)
AC.SceneSettings:PlayStartCutscene() (at Assets/Plugins/AdventureCreator/Scripts/Game engine/SceneSettings.cs:332)
AC.SceneSettings:OnStart() (at Assets/Plugins/AdventureCreator/Scripts/Game engine/SceneSettings.cs:110)
AC.SaveSystem:InitAfterLoad() (at Assets/Plugins/AdventureCreator/Scripts/Save system/SaveSystem.cs:650)
AC.MultiSceneChecker:Start() (at Assets/Plugins/AdventureCreator/Scripts/Game engine/MultiSceneChecker.cs:62)
In additional the to error in the previous post, if I do not allow Player Switching, the player objects except the last one would disappear on scene start, so the assigned myNewPlayer would become null.
Though it may appear similar, the exact error should vary based on the "Player switching" field. What was the error when set to "Do Not Allow"?
Yes, I can see this - I will have to consider how this might be gotten around.
What are the circumstances that have you consider option 1) to be the preferred choice? The ability to save individual data (e.g. inventory items) is much easier if you rely on player-switching.
Oh yes, the errors are different. When set to "Do Not Allow", the error is:
ArgumentException: Gameobject is not a root in a scene
UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene (UnityEngine.GameObject go, UnityEngine.SceneManagement.Scene scene) (at :0)
AC.KickStarter.set_player (AC.Player value) (at Assets/Plugins/AdventureCreator/Scripts/Game engine/KickStarter.cs:949)
UniversalScriptedActionFunctions.AssignPlayer () (at Assets/Ricky/Scripts/Script Function Objects/UniversalScriptedActionFunctions.cs:13)
UnityEngine.Events.InvokableCall.Invoke () (at :0)
UnityEngine.Events.UnityEvent.Invoke () (at :0)
AC.ActionEvent.Run () (at Assets/Plugins/AdventureCreator/Scripts/Actions/ActionEvent.cs:44)
AC.ActionList+d__34.MoveNext () (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:374)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at :0)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
AC.ActionList:ProcessAction(Int32) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:327)
AC.ActionList:ProcessActionEnd(ActionEnd, Int32, Boolean) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:557)
AC.ActionList:EndAction(Action) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:475)
AC.d__34:MoveNext() (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:443)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
AC.ActionList:ProcessAction(Int32) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:327)
AC.ActionList:BeginActionList(Int32, Boolean) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:294)
AC.ActionList:Interact(Int32, Boolean) (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:195)
AC.ActionList:Interact() (at Assets/Plugins/AdventureCreator/Scripts/ActionList/ActionList.cs:158)
AC.SceneSettings:PlayStartCutscene() (at Assets/Plugins/AdventureCreator/Scripts/Game engine/SceneSettings.cs:332)
AC.SceneSettings:OnStart() (at Assets/Plugins/AdventureCreator/Scripts/Game engine/SceneSettings.cs:110)
AC.SaveSystem:InitAfterLoad() (at Assets/Plugins/AdventureCreator/Scripts/Save system/SaveSystem.cs:650)
AC.MultiSceneChecker:Start() (at Assets/Plugins/AdventureCreator/Scripts/Game engine/MultiSceneChecker.cs:62)
The main reason I prefer option 1 more than using "Allow Player Switching" is that my playable characters (even for the same character) in different scenes have quite many custom components. Such as color matrix, animators, and other components. So I think setting all those parameters for each component for each playable character in each scene is very inconvenient in the development process.
I think for my case, the most convenient way would be having all the Playable Character objects ready in the scene, and then able to set the character to play by actionlist or script. But if this is not doable, I would go for option 1.
The error looks to be related to one of your Player characters have a parent Transform - try moving all to the root level in the Hierarchy if this is the case.
I'm not clear on the reason why you're adding multiple Players to the scene and then disabling them, however. Do they all represent the same person?
With option 1, it's easier to set up your characters, but - as mentioned regarding e.g. inventory items, game-saving - you'll have a lot of complications when it comes to running the game.
With option 2, it may take more to set characters up, but if AC is able to control players in the way that the switching-system is designed for, it'll be a lot easier to run once set up.
I am trying to use a hybrid of option 1 & 2: "Allow play switching" + make prefab variants if the scene's player has a too specialized component to be tuned in an actionlist.
Since I have to assign the Cinemachine to follow the player after player is switched, I attached this code to a Cinemachine Virtual Camera:
However, during scene switch, there is an error arise from the above code:
MissingReferenceException: The object of type 'CinemachineFollowPlayerAsset' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
UnityEngine.Component.GetComponent[T] () (at :0)
CinemachineFollowPlayerAsset.FollowNewPlayer (AC.Player player) (at Assets/Ricky/Scripts/Camera/CinemachineFollowPlayerAsset.cs:26)
AC.EventManager.Call_OnSetPlayer (AC.Player player) (at Assets/Plugins/AdventureCreator/Scripts/Managers/EventManager.cs:1098)
AC.KickStarter.set_player (AC.Player value) (at Assets/Plugins/AdventureCreator/Scripts/Game engine/KickStarter.cs:1022)
AC.PlayerPrefab.SpawnInScene (System.Boolean makeActivePlayer) (at Assets/Plugins/AdventureCreator/Scripts/Character/PlayerPrefab.cs:124)
AC.KickStarter.PreparePlayer () (at Assets/Plugins/AdventureCreator/Scripts/Game engine/KickStarter.cs:1154)
AC.KickStarter.Initialise () (at Assets/Plugins/AdventureCreator/Scripts/Game engine/KickStarter.cs:1119)
AC.MultiSceneChecker.Awake () (at Assets/Plugins/AdventureCreator/Scripts/Game engine/MultiSceneChecker.cs:43)
Any idea how to remove the error? Thanks a lot for your help.
One more information is that, when I click on the error in the console, it points to the "GameEngine" object of AC.
Also in the scenes, I have the switch player action in the OnStart actionlist.
Rename "Disable" to "OnDisable".
Oh thanks. Didn't realize I made such a stupid mistake.
I would like to confirm something when using "Allow player switching":
When a player go to the next scene, would the same animator controller retain if the player's sprite animator controller is changed from the default animator controller (the one in the prefab) in the previous scene?
Would the above answer be different if I use the Switch Player action in an actionlist in the new scene?
During save game & load game, would the animator controller be saved if the player's sprite child prefab has the Remember Animator component?
Yes - Remember component data should be recorded for each Player and restored when appropriate.
For a change in Animator Controller asset to be saved, you'll need to attach the Remember Animator component and check Save change in Controller?.
You will also need to ensure that the Controller assets involved are set up to be saveable - see the Manual's "Saving asset references" chapter for details on this.
Once done, though, the Controller should then be saved when both spawning the Player in through gameplay/Actions, and when saving game files - both use the same system. So long as AC is in control of the Player spawning (i.e. you're not placing Player objects in the scene files yourself), then that save data should be handled automatically.