- Home /
When to use OnCollisionEnter and OnTriggerStay and how to use rigidbody.AddForce
Hi Sorry for the long question title. I am trying to make a treadmill for a uni project. I want the treadmill/conveyor belt to move the player along its path and if the player tries to move with it they will speed up and against it they will slow down.
I have begun researching how to create this effect and I am having trouble and would like some help. I have found this previous question http://answers.unity3d.com/questions/529178/conveyor-belt-physics.html
and further research has lead me to something called rigidbody.AddForce. The AddForce sounds very ideal for what I am trying to achieve but my player (which is just a cube for now) just sits on top of my bigger cube (with the belt script attached to it) and moves when I was WASD as expected.
Even when I make my player Kinematic and go inside the belt and trigger my "touched" message to activate my player only moves when I press buttons and is not moving as intended.
If anyone can shed some light and help me achieve my results and help me understand why my attempts are failing, it would be a massive help. Thank you and here is my script... using UnityEngine; using System.Collections;
public class conveyorBelt : MonoBehaviour { private Transform conveyorBelts; private float beltSpeed;
// Use this for initialization
void Start () {
conveyorBelts = transform;
beltSpeed = 6.0f;
}
// Update is called once per frame
void Update () {
}
void OnTriggerStay( Collider other )
{
print ("Touched");
other.rigidbody.AddForce(Vector3.left * Time.deltaTime * beltSpeed);
}
/*void OnTriggerEnter(Collider collider) {
collider.rigidbody.AddForce(Vector3.left * Time.deltaTime * beltSpeed);
print ("Touched");
}*/
}
$$anonymous$$inematic rigidbodies don't move with forces. They can only be moved by script.
OnCollisionEnter() is called when a collider collides with another collider. If the collider maintains collisions it will not be called again. If the collider stops collision it will not be called again.
OnCollisionStay() and OnCollisionExit() will be called in those situations.
OnTriggerEnter() is called when a collider enters a trigger. The respective functions are the same. OnTriggerStay() OnTriggerExit()
rigidbody.AddForce(a,b.xyz); applies a force of 'a' in a direction 'b'
I hope this helps
EDIT : I've read your question fully and my advice would be look into Physic $$anonymous$$aterials
Also AddForce will add a force to the object. This will affect the velocity of the object
(Acceleration = Force / $$anonymous$$ass) (Velocity = Acceleration / Time)
This means your Velocity will constantly increase, which isn't what you want you want to Add your conveyor velocity to your objects velocity.
I would write something like this ($$anonymous$$aking sure both my conveyor and my object have a collider, my object will also have a rigidbody)
using UnityEngine;
using System.Collections;
//Class to act as a conveyor belt
public class Conveyor : $$anonymous$$onoBehaviour
{
//Public Variables
public float speed;
void OnCollisionStay(Collision other)
{
other.rigidbody.AddForce(Vector3.left * speed);
}
}
This gives you an alright effect with a sphere. I hope this is a good starting point.
Good luck with your uni project, please come back if you require any assistance :)
Thank you for your advice. I have looked into Physics $$anonymous$$aterials. http://docs.unity3d.com/Documentation/Components/class-Physic$$anonymous$$aterial.html and whilst very useful its not quite what I need. I believe this is not doing what I want is because of my player script.
I could be wrong but with my player script there is nothing which is taking into account any form of friction thus when I set my physics material to have a lot of friction, I can still move around freely.
Forgot to paste my player script :) using UnityEngine; using System.Collections;
public class Player : $$anonymous$$onoBehaviour {
private Transform player;
private float playerSpeed;
// Use this for initialization
void Start () {
player = transform;
playerSpeed = 5.0f;
}
// Update is called once per frame
void Update () {
player.Translate(Vector3.right * playerSpeed * Input.GetAxis ("Horizontal") * Time.deltaTime);
player.Translate(Vector3.up * playerSpeed * Input.GetAxis ("Vertical") * Time.deltaTime);
}
}
THAN$$anonymous$$ YOU!! I have been playing around with your script and as i wanted I actually understand now why it works. I had never heard of a physics material until tonight and adding this in conjunction with your script has granted me the results intended. Thank you. I will credit you. People like yourself make learning code fun. Thank you. :)
Answer by Exalia · Jan 24, 2014 at 01:25 AM
I'll post this as an answer then haha, I'm glad you got it working ^^
This script works with a plane and a sphere with a rigidbody, both with colliders. However the sphere rolls with this set up which wouldn't happen on a conveyor. To get rid of this create a Physic Material and set the static and dynamic friction to 0. Apply this Physic Material to the plane and you should have something similar to a conveyor
Here is the code :
using UnityEngine;
using System.Collections;
//Class to act as a conveyor belt
public class Conveyor : MonoBehaviour
{
//Public Variables
public float speed;
void OnCollisionEnter(Collision other)
{
other.rigidbody.drag = 0;
other.rigidbody.AddForce(Vector3.left * speed);
}
void OnCollisionExit(Collision other)
{
other.rigidbody.drag = 1;
}
}