Using OnCollisionEnter

So I have made my script work in my player jumps when he’s hitting any object tagged “Ground”. But in trying to clean up my code I’m having a hard time being able to call OnCollisionEnter.
This code works great

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class jumpgrounded : MonoBehaviour
{
    public float speed = 4.5f;

    private Rigidbody rb;

    public float jumpForce = 9;

    public bool cubeIsOnTheGround = true;


    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();

    }

    // Update is called once per frame
    void Update()
    {
        PlayerMove();

    }

    void PlayerMove()

    {

        float leftRight = Input.GetAxis("Horizontal");
        float forwardBack = Input.GetAxis("Vertical");
        Vector3 movePlayer = new Vector3(leftRight, 0, forwardBack) * speed * Time.deltaTime;
        transform.Translate(movePlayer, Space.Self);

        if (Input.GetButtonDown("Jump")&& cubeIsOnTheGround)
            {
                rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
                cubeIsOnTheGround = false;
            }
    }

    private void OnCollisionEnter(Collision collision)
    {
        Debug.Log("Entered");
        if (collision.gameObject.tag==("Ground"))
        {
            cubeIsOnTheGround = true;
        }
    }
}

But I would like to clean the code up my code and to call a jump method and also use OnCollisionEnter But when I do it only jumps once? So I guess you cannot call OnCollisionEnter as a method??

public class jumpgroundmethod : MonoBehaviour
{

 
        public float speed = 4.5f;

        private Rigidbody rb;

        public float jumpForce = 9;

        public bool cubeIsOnTheGround = true;


        // Start is called before the first frame update
        void Start()
        {
            rb = GetComponent<Rigidbody>();

        }

        // Update is called once per frame
        void Update()
        {
            PlayerMove();
            Jumping();
      

        }

        void PlayerMove()

        {

            float leftRight = Input.GetAxis("Horizontal");
            float forwardBack = Input.GetAxis("Vertical");
            Vector3 movePlayer = new Vector3(leftRight, 0, forwardBack) * speed * Time.deltaTime;
            transform.Translate(movePlayer, Space.Self);


        }

    void Jumping()

    {

        if (Input.GetButtonDown("Jump") && cubeIsOnTheGround)
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
            cubeIsOnTheGround = false;
        }
    }

        void OnCollisionEnter(Collision collision)
        {
            Debug.Log("Entered");
            if (collision.gameObject.tag == ("Ground"))
            {
                cubeIsOnTheGround = true;
            }
        }
    }

When you are using Rigidbodies, NEVER directly set the transform (by assigning position or using Translate). When you do that, that bypasses the physics system so you will miss collision events. Instead, calculate the new position yourself, then set it with the .MovePosition(); method of the Rigidbody reference.

You can call it, but it’s not a good idea, as that’s not how it is supposed to be used. The way it is supposed to work is that Unity calls YOU at that method.

Basically, by API contract, i.e., prior agreement between Unity and you, if you provide that method (OnCollisionEnter) spelled precisely as the API specifies with precisely the right arguments, AND you meet all the criteria for having it be called (See docs for more), then the function gets called.

In any case, to debug stuff like this, to help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run?
  • what are the values of the variables involved? Are they initialized?

Knowing this information will help you reason about the behavior you are seeing.

1 Like

So I tried changing my script using the movement command and other options Instead of transform to translate I understand this may interfere with the physics interaction in your game

But the other Scripps I tried, If they did not work well or if they did work they wouldn’t mess up the script I have on my camera to follow the player and my move buttons would then go in the opposite direction. So unfortunately until something works better I’m sticking with it for my class to follow. I know it works and we actually do collide with lmost objects

If it goes in the opposite direction, you’re not setting the vectors correctly. It will work. Again, don’t use transform, only use commands on the Rigidbody, like AddForce (the way you did with Jump). Your camera should follow the player just fine regardless of the method you use to move your player.

For the OnCollisionEnter, you just get that call one time when it first starts colliding, but then you can do whatever you need to with it. There’s OnCollisionStay too, which might be helpful.