Skip to main content
replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/
Source Link

I will assume only one of the triggerCube objects contains the EndPoint script, which allows quick assurance that the logic will only process once. You may also want to look at an alternate question, "Check which object triggered another""Check which object triggered another".

I will assume only one of the triggerCube objects contains the EndPoint script, which allows quick assurance that the logic will only process once. You may also want to look at an alternate question, "Check which object triggered another".

I will assume only one of the triggerCube objects contains the EndPoint script, which allows quick assurance that the logic will only process once. You may also want to look at an alternate question, "Check which object triggered another".

Source Link
Gnemlock
  • 5.3k
  • 5
  • 28
  • 59

As stated in the other answers, collision is only initially being handled between the two game objects that are colliding. You need to have a script on one of the two objects involved in the collision, and have it relay information back to the player, somehow.

Potential problems with same-named objects colliding

In your example, you have a script that is on an object named "triggerCube". You also check to see if the othercol.name == "triggerCube", suggesting that both objects are named "triggerCube".

It is important that you are aware that both cubes will trigger a collision. This means that if both cubes have the EndPoint script, they will each run their own version of OnCollisionEnter, where they will each see the opposite triggerCube and determine that (col.name == "triggerCube") == true.

'Why is this important', you might ask? Well, it means that your logic will be run twice. Under some logic, this won't appear to mess things up; but you might have some fatal errors, as a result. You could also have situations where the "Player" tag jumps an extra game object, depending how you have things set up, as both triggerCube objects detect a collision and individually instruct the player to 'hop objects'.

I will assume only one of the triggerCube objects contains the EndPoint script, which allows quick assurance that the logic will only process once. You may also want to look at an alternate question, "Check which object triggered another".

Alerting the Player object to collision

Ultimately, you need to be able to identify the Player script, to push action to the player when your two triggerCube objects collide. You can do this several ways, each of which has their advantages and disadvantages. We will assume that the script attached to your player is called Player.

Here are three easy ways to set up your reference:

  • Use Unity Editor: If your only making the jump once, this is the quickest and most reliable way to go.
  • Use a static script: If your only keeping one instance of the player, this might be the quickest way to go. Beware: If you do not properly ensure that you only have one Player, your going to have a bad time.
  • Find the reference on the fly with tags: If you only have one Player tag at a time, this might be the more reliable way to go. Than again, if you have a lot of objects in your scene, you might find that this method is slow to work itself out.

Passing the reference via Unity Editor

Having a public reference allows you to manually set the reference using drag and drop, in the Unity Editor.

This is a good way to test out certain functionality, while ensuring correct reference. This is also a good way to go when the reference is some what static - that is, if the script should not move from that game object, your reference should always work properly. This is also, arguably, the easiest way.

If you have to perform this sort of action again, i.e. it is not a 'one-time only' event, this is probably not the best solution. If you still go this way, you will still have to ensure that the reference is properly set up again, when you move to the next 'player object'. Since your now in-game, you will have to reset the reference without the Unity Editor, so your better off just using one of the more adaptable solutions from the start.

public class EndPoint : MonoBehaviour
{
    public Player player;

    void OnCollisionEnter(Collision other)
    {
        if(other.gameObject.name == "triggerCube")
        {
            player.NextPlayer();
        }
    }
}

public class Player : MonoBehaviour
{
    public void NextPlayer()
    {
        // Move tag to next object;
    }
}

Keeping a static reference to Player

Having a static reference allows you to guarantee access to your script, but you should remember that to be static, a script can not have instanced variations in play. While you are not hard-bound by this constraint in using static, if you do not follow the logic, bad things will happen.

You could consider attaching the script to your new 'player object' with each NextPlayer(), if you need to move players more than once. If your logic insists that multiple Player scripts be at play at the same time, this will not work for you. If you have multiple Player scripts, with only one at play at a single time, you still need to make absolute sure that Player.me references the active version of your Player script. Even with precision, that could be tricky.

public class Player : MoboBehaviour()
{
    public static Player me; // cheeky self-reference

    void Start()
    {
        me = this;           // set up the self-reference
    }

    public void NextPlayer()
    {
        // Move tag to next object;
        // Attach this script to the next object;
        // That way, this static script can be kept,
        // but it still references the next object with this.gameObject
    }
}

public class EndPoint : MonoBehaviour
{
    void OnCollisionEnter(Collision other)
    {
        if(other.gameObject.name == "triggerCube")
        {
            Player.me.NextPlayer();
        }
    }
}

Finding Player on the fly with tags

Another option you have is to locate the player using the same tag you wish to change.

This solution is more likely to work on the fly, in a variety of circumstances. That said, we are relying on checking all objects for the Player tag; while the scenario you describe seems to imply only one Player tag will be in use (so we are not worried about finding the wrong object), you have to keep aware of how many game objects are currently in your scene. As your logic has to sort through more objects to find the player, it will take longer to complete its operation.

public class EndPoint : MonoBehaviour
{
    Player player;

    void OnCollisionEnter(Collision other)
    {
        if(other.gameObject.name == "triggerCube")
        {
            FindPlayer();
            Player.NextPlayer();
        }
    }

    void FindPlayer()
    {
        GameObject.FindWithTag("Player");
    }
}

public class Player : MonoBehaviour
{
    public void NextPlayer()
    {
        // Move tag to next object;
    }
}

Moving the "Player" tag

Now that's all sorted out, changing the tags should be quite easy. Simply calling gameObject.tag = in a script should give you the ability to change its tag. That said, you must ensure you set a tag that has previously been set in the Tags & Layers Manager.

If it was not already obvious, you will have to retrieve a reference to your 'new player object', just as you had for your player. You should be able to do this in effectively the same way as you would to identify the initial 'player object'.

You may consider using a different method to that which you used for Player. Keep in mind that since you may not be calling any real script logic on the other side, yet, you may not have an actual script on the other side. You can store a reference to the direct game object with GameObject nextPlayerObject, and work your way from there.