Forum rules - please read before posting.

Settings Manager' Player prefab requirements vs VR Player setup

edited March 2022 in Technical Q&A

Hi All!

I dream of making a "VR point and click" adventure game (imagine for example the Day of the Tentacle in the VR) ;)

I'm playing around with VRIF (https://assetstore.unity.com/packages/templates/systems/vr-interaction-framework-161066) + AC and have some good progress so far (world space VR UI for Subtitles and Hotspots - as prefabs!; triggers, VR FPP vs "cinema" cameras movements, movement blocking during cutscenes etc.). A lot of cool stuff :)

The thing I come by with is not a bug report, but an integration trouble and I'm looking for help or hint.

Here is a problem:

  • AC's Settings Manager for Player prefab needs to have AC's Player script attached to the root (parent) node of player's GameObject.
  • Object with AC's Player script needs to be moved in the scene (the yellow orb - to detect hotspots, trigger triggers and so on)
  • VRIF player's structure has a non-movable root node (let's call it "XR Rig") and movable PlayerController as a child node (moved by its local position)
  • Having AC Player script attached to the XR Rig works for the Settings Manager Player prefab requirement, but while PlayerController moves the AC Player doesn't, thus most of AC based interactions are useless
  • Having AC's Player script attached to the XR Rig and trying to move based on PlayerController.transform causes infinite moving loops (moving child node moves parent that moves child even more... wrooom! and you are out of screen)
  • Having AC's Player script attached to the PlayerController works great, but Settings Manager doesn't allow to use it as a Player's prefab
  • Skipping Settings Manager and just placing directly in the scene the XRRig with AC Player script attached to the PlayerController could work, but I have to always remember to add it to each scene, and in adition, it causes some troubles:

    • being already in the scene, PlayerController detects no EventSystem so it creates its own, AC detects it and skips adding its own EventSystem prefab I configured in the Menu Manager...
    • adding manually my "AC ready" EventManager to the scene is not cool, cuz it's another object I need to remember to add manually, and AC warns me that: "A local EventSystem object was found in the scene. This will override the one created by AC, and may cause problems." (and I don't want more problems)
  • I also tried to ditch XR Rig and just use PlayerController as a root node with AC's Player script attached, but it seems that XR Rig structure was created not without a reason - it lost some VR capabilities (such as moving the player in the direction of the head turning)

I rely on two asset providers (AC and VRIF) to have a player object, so I want to keep it simple for the sake of upcoming updates.

I'm looking for an idea to trick the system and have AC's Player script attached to a child gameobject of a VR player and still use it as a Player's prefab in the settings Manager;
or
to make the root gameobject (XR Rig with AC Player) follow the transform of its child called PlayerControler from VRIF asset (without any transform interference issues);
or you have a better idea :)

I tried to learn something from https://adventurecreator.org/tutorials/adding-custom-motion-controller
and from Opsive UCC integration, but in both projects the player's root node is movable and there is no issue like mine.

Will appreciate any thoughts or ideas :)

Thanks,
Barnim

Comments

  • Welcome to the community, @Barnim.

    AC's Settings Manager for Player prefab needs to have AC's Player script attached to the root (parent) node of player's GameObject.

    Editor fields for a specific component type only accept prefabs that have the component on their root - this is Unity's built-in behaviour.

    If you want to keep your Player component on a child of your prefab, but avoid placing it in the scene file, you should be able to spawn it and initialise via script. The scene's active Player can be assigned with:

    AC.KickStater.player = myNewPlayer;
    

    It may not be necessary to resort this this, however:

    Object with AC's Player script needs to be moved in the scene (the yellow orb - to detect hotspots, trigger triggers and so on)

    If your Settings Manager's Hotspot detection method is set to Mouse Over or Custom Script, the Player's position isn't strictly a factor in things. If set to "Mouse Over", then it's a case of camera position and raycast lengths. If "Custom Script", then you can control exactly what Hotspot is controllable through scripting - see the Manual's "Custom interaction systems" chapter for details.

    Regarding Triggers: the default settings of the Trigger object are set to detect the Player, but this can be modified to instead to react to a given component, tag, or object.

    VRIF player's structure has a non-movable root node (let's call it "XR Rig") and movable PlayerController as a child node (moved by its local position)

    Having AC Player script attached to the XR Rig works for the Settings Manager Player prefab requirement, but while PlayerController moves the AC Player doesn't, thus most of AC based interactions are useless

    Having AC's Player script attached to the XR Rig and trying to move based on PlayerController.transform causes infinite moving loops (moving child node moves parent that moves child even more... wrooom! and you are out of screen)

    Putting interactions aside for the moment, it may be viable to keep the Player on the root and fixed in place - with AC not controlling the Player's position at all. You can set the Player component's Motion control field to Manual to keep the Player object in place, and rely on a separate system to move either them or a child object without AC interfering.

    being already in the scene, PlayerController detects no EventSystem so it creates its own, AC detects it and skips adding its own EventSystem prefab I configured in the Menu Manager...

    That'd be a case of editing the non-AC PlayerController script.

    adding manually my "AC ready" EventManager to the scene is not cool, cuz it's another object I need to remember to add manually, and AC warns me that: "A local EventSystem object was found in the scene. This will override the one created by AC, and may cause problems." (and I don't want more problems)

    If it comes to it, having to add one or two objects to a given scene isn't that big of an issue, IMO. Again, it could be spawned in via script in a custom Awake function - just set the script's execution order to something lower than that of PlayerController so that it spawns first.

    Don't be put off by AC's warning message regarding problems. If you're overriding an EventSystem in the Menu Manager, the effect on AC will be the same. AC's default EventSystem is customised mainly in the areas of allowing for separate direct-navigation of menus with controllers, which wouldn't be used in a VR project.

  • Thanks @ChrisIceBox for your warm welcome and for your extensive answers!
    This is more than helpful.

    I think I will go with having Player added manually to the scene. I already have a separate prefab for AC MainCamera with Tracked Pose Driver added for VR, so as you said, a couple of objects manually added to the scene is not a big deal.
    I've just tried playing around with Script Execution Order to check if I can get rid of this "Local EventSystem found" warning, but with no luck so far. I added AC.Kickstarter script and put it at the top (above VRIF scripts). Not sure if it's the right way to do it.

    I will have a closer look at your answers and test everything later.
    Anyway, thanks again, your answers are inspiring!

    Thanks,
    Barnim

  • edited March 2022

    You're welcome!

    I added AC.Kickstarter script and put it at the top (above VRIF scripts). Not sure if it's the right way to do it.

    AC's core scripts have a lot of interdependencies and orderings when it comes to the startup process, so don't add KickStarter to anything manually.

    The "local EventSystem" message will show any time that AC is unable to spawn in it's own, however. My mention of the Script Execution Order was more to do with making sure your own EventSystem gets spawned in before AC's does - in the event that you want to automate its addition to the scene, rather than manually placing it in the scene file.

  • edited March 2022

    Okay, thanks, now I get it.

    Now I struggle with having the Player script on a root node and some strange thing happened to me:

    Could you please explain to me how this is possible?

    I added Player script to the root object of XR Rig. As mentioned before, my VR movable player is PlayerController (a child of XR Rig) and most of gizmos that you see in the Scene view are put on that Object.
    I expected that when I move the root object, all children will follow.
    So, I thought if it works, the only problem I must fix is to make Triggers work ona Player Tag discovery - still don't know how to do that.
    But.
    When I start the game, I use OnStart Action to move the player to Marker (pathfinding).
    As you can see ona a gif, it moves the yellow orb (the Player on a XRRig - root object) but it doesn't move the child objects. Funny enough it can rotate them.
    What? How? Why?
    I was not able to move Root object to follow PlayerController without impact on the PlayerController, because of movement looping.
    I don't get it :)

    Link to the original gif (just in case embedded is not big enough):
    https://imgur.com/AMEomWh

  • If the yellow gizmo / root object is moving, then AC is working as intended - and it won't be forcing the child objects to remain in position. The behaviour you're getting from the XR Rig is down to the XR Rig itself - AC won't be involved with that.

  • edited March 2022

    Thanks for a very quick reply!

    You were right. I used an empty GameObject with Player and Paths scripts added and put a cube as a child object and it followed the player. So, it means that XR Rig keeps its objects in place. Too much auto-magic for me.

    This means for me, to keep things as simple as possible, I must have a Player script added to the PlayerController (a child of XR Rig) and spawn Player prefab by a custom script.
    I managed to do that, and now I have a single Prefab called VRSceneStart that is the only one I need to add to each scene.
    This object has a script called OnSceneStart that spawns prefabs of the VREventSystem and VRPlayer in the Awake method and assigns them in the Start method.

        void Awake()
        {
            if (vrEventSystemPrefab == null)
            {
                Debug.Log("vrEventSystemPrefab  is null.");
                return;
            }
            vrEventSystem = Instantiate(vrEventSystemPrefab, new Vector3(0, 0, 0), Quaternion.identity);
            eventSystem = vrEventSystem.GetComponent<UnityEngine.EventSystems.EventSystem>();
    
            if (vrPlayerPrefab == null)
            {
                Debug.Log("vrPlayerPrefab  is null.");
                return;
            }
            vrPlayer = Instantiate(vrPlayerPrefab, new Vector3(0, 0, 0), Quaternion.identity);
            acPlayer = vrPlayer.GetComponentInChildren<Player>();
    
        }
    
        // Start is called before the first frame update
        void Start()
        {
            if (acPlayer == null)
            {
                Debug.Log("acPlayer  is null.");
                return;
            }
            AC.KickStarter.menuManager.eventSystem = eventSystem;
            AC.KickStarter.player = acPlayer;
        }
    

    Is this ok?

    VRSceneStart also has a child object:

    • VRMainCamera GameObject with only AC's MainCamera script, and a child object called(and tagged) MainCamera with Camera and Tracked Pose Driver (to move it with VR head) scripts attached.

    This way all triggers work, player movement (vr+ac) by input and ActionLists works great, hotspots by custom scripting work.

    The only thing I'm unable to fix is to get rid of this warning: "A local EventSystem object was found in the scene. ", but I guess I have to live with that.

    Does this setup look good? What would you improve?

  • edited March 2022

    It'd be worth trying to move the Start function code to an OnInitialiseScene custom event hook, which is triggered once AC has spawned in its own objects but before any data/initialisation routines are applied, i.e.:

    private void OnEnable () { EventManager.OnInitialiseScene += OnInitialiseScene; }
    private void OnDisable () { EventManager.OnInitialiseScene -= OnInitialiseScene; }
    
    void OnInitialiseScene ()
    {
        // Start code here
    }
    

    Regarding the event system: the message from AC will always show if an EventSystem object is found in the scene before AC can add its own.

    The above is actually the same event hook used by AC to spawn in the EventSystem prefab - so you might be able to have yours run first by giving it a lower Script Execution Order and remove the EventSystem from the scene so that AC finds it safe to spawn. Functionally, though, there should be no difference.

  • I was not able to get rid of the warning message. Either my script is run too early or too late. I give up - it's not worth effort, and as you said it has no real impact on anything.
    Thanks again, Chris!

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.