- Home /
Simple collision?
Hello!
I'm writing a fairly basic game to learn C# with, so I didn't want to use any pre-made assets or scripts. I have a fps control system and everything is working great!
The player walks around a simple square room, and obviously shouldn't be able to go through the walls. I can use OnCollisionEnter and OnCollisionExit, and they both work at detecting when the collider has intersected with something. However, this does not prevent the character from going through the walls and objects.
Is there an easy way to prevent 2 game objects from going through each other?
I can think of a few ways to do accomplish/fake the effect I'd like, such as only allowing movement in a direction up to a certain value, but I feel like it wouldn't be useful in an actual game, because I won't always be dealing with prefect squares.
What would be the 'official' way of preventing an object from intersecting?
Yes, the purpose of this project is to help me learn C#, not to make a fancy, functioning game. Using the character controller wouldn't help me :)
Not sure how that follows; using a character controller is part of learning Unity and C#. Nothing to do with making a functioning game--use the appropriate tools for the job.
True, the character controller is helpful and would make the job easier, but I've already played around with it for a bit the past few days. I know there's no point in reinventing the wheel, but for the sake of trying to think in terms of a program/game, I feel it would be more helpful to come up with my own solution. I guess I could probably set the translation of the character in the normal direction equal to 0 while contact with the wall is true. That could work... right?
Aside from the character controller, collision generally works using rigidbodies and adding forces, not directly translating, except for Rigidbody.$$anonymous$$ovePosition.
Answer by N1GHTMAR3 · Oct 25, 2012 at 05:31 AM
If OnCollisionEnter and OnCollisionExit is working, i think you are using Translate to move the player. To prevent the player from going through the walls you must add character controller component to your player and use CharacterController.move instead.
This code is from Unity Scripting Reference.
PD: Excuse my english.
using UnityEngine;
using System.Collections;
public class example : MonoBehaviour {
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
void Update() {
CharacterController controller = GetComponent<CharacterController>();
if (controller.isGrounded) {
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
}
Answer by NickelBuckle9 · Oct 27, 2012 at 10:34 PM
Ok, so I think I figured it out... in case anyone else is interested, here's what I did.
I put a collider around my character, and added a rigid body to it, as needed by the OnCollisionEnter() script. Using OnCollisionEnter, I have it calculate the normal direction of the object with which it collides, and set a hit boolean to true false to see if contact was made. Then, I use the x and z components of that normal vector in the translation of my character when the collision is true.
It works relatively just like I wanted it to, but I have to divide the components by 1000 so that it doesn't jump back and forth rapidly as you try to enter the wall.
Code in C#:
CollisionDetect script:
using UnityEngine;
using System.Collections;
public class CollisionDetect : MonoBehaviour {
public static bool Hit = false;
public static Vector3 Wall = new Vector3(0,0,0);
public void Awake () {
Wall = new Vector3(0,0,0);
Hit = false;
}
void OnCollisionEnter(Collision collision) {
ContactPoint contact = collision.contacts[0];
Wall = contact.normal;
Hit = true;
}
void OnCollisionExit(Collision collisionInfo) {
Hit = false;
}
}
WASDmovement Script:
using UnityEngine;
using System.Collections;
public class WASDmovement : MonoBehaviour {
public float speed = 10f;
public float rotate = 90f;
void Update() {
if(CollisionDetect.Hit == true){
transform.Translate ((CollisionDetect.Wall.x)/1000,0,(CollisionDetect.Wall.z)/1000, Space.World);
float y = rotate * Time.smoothDeltaTime * Input.GetAxis("Horizontal");
Debug.Log(CollisionDetect.Wall);
transform.Rotate(0, y, 0);
}
else{
float moveForward = speed * Time.smoothDeltaTime * Input.GetAxis("Vertical");
float y = rotate * Time.smoothDeltaTime * Input.GetAxis("Horizontal");
transform.Translate (0, 0, 1 * moveForward);
transform.Rotate(0, y, 0);
}
}
}
Your answer
Follow this Question
Related Questions
Button to change layers 1 Answer
Get objects in collision 1 Answer
Multiple Cars not working 1 Answer
OnCollisionEnter2D not being called on entering new tile once already called. 1 Answer