I am currently implementing player switching and am hitting some roadblocks.
Whenever a switch occurs, the previous character should stay it it's last position and be interactive with the new player.
I used player switch and teleport actions to switch player and move the NPC placeholder far away. This works nicely but:
If I switch to a character, that is in another scene, the teleport action doesn't run since the ActionList was part of the last scene(even though it's an asset). So far I didn't find any usable solution. I could create a separate action list in the new scene, that would trigger OnLoad and check for any NPC placeholders that need to be moved, but since we have over 100 scenes, this is not a very viable option.
My solution: I would use just one prefab for the player and NPC: it would have all components for player and NPC, where the NPC scripts would be disabled. Whenever the player gets switched, my custom switch action would first change the gameobject tag from Player to something else and enable those NPC scripts(and maybe disable Player scripts).
And because that object no longer has Player tag it wont get removed when KickStarter.ResetPlayer() runs.
It works fine but my only issue is, that the object is not persistant. It doesn't save with the scene so whenever we come back to this scene the NPC is gone. I added remember NPC and remember transform scripts with no success.
Is this approach alright? If yes, how could I make AC save the NPC gameobject?
Comments
HarryOminous thank you for your opinion and suggestion. I see that we both have similar problems and different solutions. I was first attempting to use two prefabs for each character, a player and a NPC one. This solution however might be over complicated since in case we need to change lets say sprites of some body parts we need to do it in both prefabs. That is not ideal.
Thats why I was trying my approach of one prefab that gets "decoupled" once it gets switched with another player. The object stays behind and NPC related stuff gets enabled.
I managed to get it to work now by adding those prefabs to the Resources folder and setting up Remember Transform components. It works pretty neat, even switching from and to another scene works fine. I also added a hotspot and interactions with asset related action lists and it worked neatly, even character follow and talk works.
My only issue now is that if lets say an NPC that was a player gets moved by Keep out of players way? or Player follow and gets then switched back as the player it will jump to it's original position.
Is there any solution implemented to save player positions by code or while moving?
Thanks again for your help!
PS:(my original comment got deleted after I edited it, could be a forum related bug)
After wasting a whole week with player switching I figured that this might not be the best solution. Switching players in the same scene is working fine but as soon as the new player is in a different scene everything falls apart.
Sometimes there is no player in DontDestroyOnLoad, sometimes the default camera gets changed and sometimes there are duplicate objects with the Player tag. So I dropped my whole idea and used a different set of prefabs for NPCs instead.
Those work fine althought there are some issues of which I managed to sort some out.
1. Switching player that is in a different scene won't remove his placeholder NPC. So I wrote an Awake() function that checks if that NPC is the player and removes it.(using Kickstarter.scenechanger.ScheduleForDeletion(). I hope this is fine?)
2. I had to create many Actions for every player switching scenario. For example, I have 5 players, so I need about 4 Action times 5. (figuring out which NPC to replace it and some other stuff). So I copied your PlayerSwitch Action and added this stuff in code. It now also checks if switching is made in same scene so the script itself removed the placeholder NPC instead of the Awake() function.
3. Switching between characters to other scenes sometimes switches to default (0) character and puts the one that was supposed to be switched to to pos 0,0. Not sure why as of yet.
4. Last week before I've written a single line of code I asked how to make objects stay in scene after switching forth and back. You told me to add a RememberTransform component which I did and it worked fine. Right now I do not have any Remember components attached but they still stay when coming back. I do however have a ConstantID attached. Is this enough to serialize the object and load it back? If yes, super!
In conclusion: I made separate NPC prefabs to be replaced to as you suggested. I used a modified version of PlayerSwitch Action that has references of all PlayerNPC prefabs and uses the corresponding one. I attached a script to every PlayerNPC prefab that Destroys the object if it has the same name as the player.
Sorry for the long comment!
2. I don't know the exact contents of each of those ActionLists, but it may be that use of ActionList parameters can be of use here. Like function parameters, ActionList parameters are designed to let you "recycle" Actions by altering their fields dynamically when run.
3. Sounds like a bug, but I'll need more details and steps to recreate. If you can learn more about the conditions that cause this, please let me know.
4. Which objects, NPCs? That shouldn't be the case - though it may be that Unity now remembers such changes when testing in the Editor. Use of the Remember Transform component is necessary for reliable dynamic object saving.
3. I managed to find the issue. Some scene's default cameras didn't yet have a ConstantID so sometimes camera would go to MainCamera(that is created with scene setup) and switches to default(0) player. Not sure if this is the exact cause but after I attached ID scripts to all cameras the bug was gone. Very weird.
4. Yes NPCs that are instantiated in place of the player. Previously they would disappear when I switched scene forth and back, now they are still there, even after saving and loading game. I do have a RememberTransform on them but it's disabled. All I have is ConstantID. If this is sketchy then I shall re-add those RememberTransforms oh PlayerNPC prefabs just to be safe.
All in all, player switching now seems to work like it's suppost to.
I skipped using a spaghetti of ActionLists by making my custom Switch. I feel this way I have more control over everything and I can replace an Action with a simple line of code.
I did use objects ad ActionList parameters once but only for in-scene. Do they not hold a constantID? That would explain why you get a NullRefException.
1. Actually I was mistaken - this functionality should already be in there. You haven't stated your Unity/AC version numbers, but assigning an NPC in the Player: Switch Action's NPC to be replaced field should cause an automatic removal of that NPC. I have uncovered some related bugs however (see below).
3. That's as intended - whereas Remember components save changes made to a component, the ConstantID component saves references - i.e. which camera in a scene is active. This is covered in the Manual's "Saving scene objects" chapter, but AC can attempt to add necessary save components via the top of the Settings Manager. If such a component is missing upon saving, the Console should warn you about it.
4. Interesting, what's your Unity version? I'd expect this wouldn't be the case in builds.
@HarryOminous:
Passing a prefab as a parameter should work - are you working with ActionList assets or scene-based ones? This sounds like it isn't solely to do with player-switching, so please post full details in a new thread so that I can recreate.
OK, now on to my own testing..
So I've been through the general workflow for creating a multi (3 or more) player-switching game mechanic, and there are admittedly a few problems. I'll be addressing them as part of the upcoming v1.64 update. In summary:
@ChrisIceBox
Your solutions sounds great! But since I already got it working 100% I wouldn't dare scrambling around again. I'll wait for your upcoming fixes and then consider changing the way it works.
Something else: Is there any randomizing Action in AC? If not, it would be great to have one. It would be great for let's say randomizing some NPC responses or animations.
I found a way to do this with parameters and setting them to random. But this action would still only have two outputs, true and false. What about having a dynamic range of more than two outgoing actions? This would be great!