0
votes

I'm new to Unity and struggling to get the OnCollisionEnter function to pick up.

I realize this sounds similar to other questions, but I still can't get it to work for my case.

I'm using the Oculus Distance Grab Sample Scene.

I've got a block trying to run into a soccer ball ;)

The block has a box collider (non trigger) and rigid body (non gravity, non kinematic).

The soccer ball has a Sphere Collider (non trigger) and a rigid body (yes gravity, non kinematic).

The block contains a script component that makes it float over to the ball and run into it.

The ball has a script with the OnCollisionEnter function that is supposed to destroy the block upon contact.

Here's the Player script attached to the ball.

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

public class Player : MonoBehaviour
{
    void OnCollisionEnter (Collision col) {
        FloatingItem item = col.collider.gameObject.GetComponent<FloatingItem>();
        Destroy(item);
    }
}

The ball is in the Player layer and the block in the Attacker layer. I double checked collision were enabled between these layers in the Player Settings collision matrix.

Also, the colliders of each object seem to be the size they should to match the mesh.

Any help to get the collisions working would be wonderful!

Here's a visual of the settings as well:

enter image description here enter image description here

UPDATE:

Here is the floating block's Update method:

void FixedUpdate () {
      if(targetTransform != null) {
        this.transform.position = Vector3.MoveTowards(this.transform.position, targetTransform.transform.position, Time.deltaTime * moveSpeed);
      }
    }

I have been trouble getting any debug logs to show in the console so they haven't been reliable. But the answer was that the collision was in fact working but that I was destroying the wrong object.

Changing it to Destroy(col.collider.gameObject) works. An important distinction learned here! Thanks!

UPDATE 2:

I've added an image of how the OVRPlayerController is setup. Trying to read through the weak documentation about the character controller component of this but my understanding is that it contains a capsule collider.

enter image description here

1
Please show in particular the code for The block contains a script component that makes it float over to the ball and run into it. Spoiler: Anything having a Rigidbody should only be moved via MovePosition within FixedUpdate otherwise Physics don't work well. If the block is moved by script you might also want to enable isKinematic except it shall react to Physics - derHugo
right now you are only destroying the FloatingItem script and not the whole GameObject. Did you check with Debug.Log("collision"); if the collision was triggered? - nka_Zz
@derHugo if you use MovePosition every frame, isKinematic should definitely be on, or it is equivalent to setting rigidbody.position. If you want collisions, you should simply set the velocity on the first frame. - Louis Garczynski
@LouisGarczynski you wouldn't use it every frame though but in fixed time intervals (usually 0.2 seconds) - derHugo
As @nka_Zz pointed out I was not destroying the game object correctly. Now it works when the block collides with the soccer ball. But this originally came from trying to have the block collide with OVRPlayerController. It still does not work in that case. Any thoughts? - Frankie

1 Answers

1
votes

Whenever there is a Rigidbody involved you should NOT set the

transform.position = Vector3.MoveTowards(...);

but rather go through the Rigidbody component e.g. using MovePosition

Rigidbody.MovePosition moves a Rigidbody and complies with the interpolation settings. When Rigidbody interpolation is enabled, Rigidbody.MovePosition creates a smooth transition between frames.

This keeps the Physics intact while moving via the transform.position creates a hard jump which will not react to collisions!

// If possible already reference this via the Inspector
[SerializeField] private Rigidbody _rigidbody;

public Rigidbody target;

private void Awake()
{
    if(!_rigidbody) _rigidbody = GetComponent<Rigidbody>();

    // Always when controlling your position by script the Rigidbody 
    // should be kinematic
    _rigidbody.isKinematic = true;
}

private void FixedUpdate ()
{
    _rigidbody.MovePosition(Vector3.MoveTowards(_rigidbody.position, target.position, Time.deltaTime * movespeed));
}