Player Collision in Udon

If you want to make something happen when the player collides with a trigger, e.g. runs into an area or touches some object, you will have to detect that collision.

IMPORTANT NOTE: As mentioned by momo in the replies this method might/will be removed at any point.
Use it only for temporary testing, or expect it to break at any point. You can still use the method below, however since VRChat will implement an “actual” way of Player Collision detection it is probably best to wait. Alternatively you can use the old method I used which is at the bottom.

A new method was pointed out by @momothemonster on the VRChat Discord. (Also thanks to @PhaxeNor for a rough code template).
To get a PlayerAPI from an OnTriggerEnter/Stay/Exit event you can use the following piece of code in U#:

void OnTriggerEnter(Collider other)
    {
        string otherAsString = ((object)other).ToString();
        if (otherAsString.Contains("VRCPlayer"))
        {
            VRCPlayerApi player = VRCPlayerApi.GetPlayerById(int.Parse(otherAsString.Split(' ')[2]));
            OnPlayerEnter(player);
        }
    }

    void OnPlayerEnter(VRCPlayerApi player)
    {
        Debug.Log(player.displayName);
    }

If you dont know how to convert that into a graph and you only use the graph then you will have to wait till I have the time to do that, or ask someone who can help you with it :slight_smile:



This is the (OLD) setup that I used before:

DISCLAIMER: This system has one big disadvantage: Every Layer that is not “MirrorReflection” will stop the UI Raycasts used for Pickups, Interact-objects and UI Menus. If the Trigger is *inbetween you and the other object you will not be able to interact with it. This does not happen if your hand is inside the collider.

  1. Create a new layer and call it something like “OnlyCollideLocal”
    grafik

  2. In your Project Settings under Physics, setup the collision matrix so that the layer only collides with “PlayerLocal”:

  3. Now make sure that the GameObject the player should collide with has a Collider (set to IsTrigger) and set the Layer to the one you just created. (If the Trigger is not static, it really should have a Rigidbody, even if you dont want it to move -> Set it to IsKinematic)

  4. On the UdonBehaviour now add whatever logic you want to happen when the local player enters/exits/stays. Here is an example:

Note that this will only work for the local player collision detection. If you want things to happen when any player walks through your collider you have two options.

  1. You send a networked event to any UdonBehaviour you want to receive the event on with the target set to all. This will essentially tell everyone “Some player has collided with that collider”.
  2. You add “Player” to the layer collision. However then you will completely lose the ability to tell which player entered the collider.

It is also worth to note that ofcourse nothing else will now collide with this particular collider. If you want to also have something happen when other objects (non-players) enter the trigger or maybe even an actual “physical” collision, then you will need to create another GameObject with a new collider. Dont use the collider described in this setup for anything else, but Player Collision Detection!

Some more technical Info:
If you find a better method please let me know so I can update this guide!
This is essentially reimplementing the “OnTriggerEnter” behaviour you know from Triggers. However Triggers can use the layer mask, because they acces the collider object and compare its layer to the layers you specified.
And you can still do that as long as you can access the object to compare its layer. However if the object returns null (like in the case of the player) you cannot get its layer to compare it.
Thereby one solution is to only collide with the local player by setting up a layer like this. This ensures that when you get a collision event it must be the local player.

13 Likes

How do i get to the project settings tab? I dont have one already there is all and a bit confused on how to get it there.

GIYF, Edit > Project Settings
https://docs.unity3d.com/Manual/comp-ManagerGroup.html

2 Likes

I have attempted to re-create this using VRCSDK3-UDON-2020.06.16.20.53_Public, and I have not been able to cause the trigger to fire with an actual player. It works fine with a cube on the PlayerLocal layer, but when I test, a real player does not fire the trigger.

Could anyone repro this and see if it works for them on that version of the SDK? This appears to be the easiest way to detect player collision, and it’s concerning that its not working.

Oops! Just found out we’ll be removing the ability to call ToString() on objects, which is the hack that this uses. Best not to use this method. The good news is that we’ll have proper Player Collision events in very soon.

Yeah was already feeling like that is pretty hacky. Dont know if I will mark the guide as “Obsolete” or “Outdate” or just delete it when the new method comes around.