Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Collision Help! How to make my player stop when hitting a cube?

Discussion in 'Physics' started by Food_Lover, Feb 9, 2015.

?

Can this be done

Poll closed Feb 16, 2015.
  1. Yes

    100.0%
  2. No

    0 vote(s)
    0.0%
  3. Depends

    0 vote(s)
    0.0%
  1. Food_Lover

    Food_Lover

    Joined:
    Dec 29, 2014
    Posts:
    16
    First of all I would like to say this could normally be easy done BUT in the game I'm working on the player is moving via a transform script so it moves 1 block at a time meaning that when it moves along one click it will be out of the wall the next click it goes into the wall. I would like to get some code to help detect the wall but I have had no luck. I write scripts in C# so anything else I won't understand.

    Video:

    (P.s The graphics will be better in the future)
    (P.P.s That is a soon to be laser :p Lol it's a work in progress. Im new to unity)
     
  2. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    317
    I don't know if that is what you want but if I understand correctly, you should cast a ray in the direction the player wants to move. If the ray hits any object and the distance in SMALLER than the distance you player would like to move then you know the player would hit a wall or be inside a wall and then you can stop the player from moving.
    (http://docs.unity3d.com/ScriptReference/Physics.Raycast.html)
     
    Food_Lover likes this.
  3. Food_Lover

    Food_Lover

    Joined:
    Dec 29, 2014
    Posts:
    16
    Hmm I have heard of raycasting before but I have never used them. I'm a pretty fast learner so it shouldn't be hard. Thanks for the reply I'll go check it out
     
  4. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    317
    Maybe also check some videos on Youtube, the docs tell you everything whats there but sometimes its best to see it in context of a game.
     
    Food_Lover likes this.
  5. Food_Lover

    Food_Lover

    Joined:
    Dec 29, 2014
    Posts:
    16
    Yeh i did. I got it all planned out and it should work apart from a few error's Im getting.
    Do you know how to fix or where I can learn how to fix the following:
    An object reference is required to access non-static member `UnityEngine.RaycastHit.transform'

    and also:
    `Varible' conflicts with a declaration in a child block

    Edit:
    With the `Varible' conflicts with a declaration in a child block error, I have found out it depends in different situations so here's my code:



    using UnityEngine;
    using System.Collections;

    public class Player_Movement : MonoBehaviour {

    public bool BlockLeft = false;
    public bool MonsterLeft = false;
    public bool BlockRight = false;
    public bool MonsterRight = false;
    public bool BlockForward = false;
    public bool MonsterForward = false;
    public bool BlockBack = false;
    public bool MonsterBack = false;
    void Update () {

    // Laser Detection
    if ( Physics.Raycast (transform.position, Vector3.left, 1)) {
    if ( RaycastHit.transform.gameObject.gameObject == "Laser" ) {
    bool MonsterLeft = true;
    }
    }
    if ( Physics.Raycast (transform.position, Vector3.right, 1)) {
    if ( RaycastHit.transform == "Laser" ) {
    bool MonsterRight = true;
    }
    }
    if ( Physics.Raycast (transform.position, Vector3.forward, 1)) {
    if ( RaycastHit.transform.gameObject == "Laser" ) {
    bool MonsterForward = true;
    }
    }
    if ( Physics.Raycast (transform.position, Vector3.back, 1)) {
    if ( RaycastHit.transform.gameObject == "Laser" ) {
    bool MonsterBack = true;
    }
    }


    // Laser Kill
    if ( Input.GetKeyDown(KeyCode.LeftArrow) == true && MonsterLeft == true ){
    transform.Translate(-1, 0, 0);
    Destroy(this);
    // Put Kill Code Here
    }
    if ( Input.GetKeyDown(KeyCode.RightArrow) == true && MonsterRight == true ){
    transform.Translate(+1, 0, 0);
    // Put Kill Code Here
    }
    if ( Input.GetKeyDown(KeyCode.UpArrow) == true && MonsterForward == true ){
    transform.Translate(0, 0, +1);
    // Put Kill Code Here
    }
    if ( Input.GetKeyDown(KeyCode.DownArrow) == true && MonsterBack == true ){
    transform.Translate(0, 0, -1);
    // Put Kill Code Here
    }


    // Movement
    if ( Input.GetKeyDown(KeyCode.LeftArrow) == true && MonsterLeft == false && BlockLeft == false ){
    transform.Translate(-1, 0, 0);
    }
    if ( Input.GetKeyDown(KeyCode.RightArrow) == true && MonsterRight == false && BlockRight == false ){
    transform.Translate(+1, 0, 0);
    }
    if ( Input.GetKeyDown(KeyCode.UpArrow) == true && MonsterForward == false && BlockForward == false ){
    transform.Translate(0, 0, +1);
    }
    if ( Input.GetKeyDown(KeyCode.DownArrow) == true && MonsterBack == false && BlockBack == false ){
    transform.Translate(0, 0, -1);
    }
    }
    }​
     
    Last edited: Feb 10, 2015
  6. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    317
    Ok, your first error says, that you have to have an OBJECT of the Type RaycastHit. But you are trying to use the CLASS. So you need to create a RaycastHit Object first and then you can get the infos from that.
    You have to use the other variant of the Raycast (it is in the docs below the first example). There you have to give the Raycast an RaycastHit object and the Raycast will fill that with all the information you need. After that you can use that RaycastHit object for getting the transform.gameObject etc.

    RaycastHit hit;
    if (Physics.Raycast(transform.position, Vector3.left, 1, out hit))
    if ( hit.transform.gameObject.gameObject.tag == "Laser" ) {

    Note that you also can't use gameObject=="Laser", you have to check gameObject.tag or gameObject.name

    Your second error means, that you declared the variable MonsterLeft at the beginning of your class and later in the laser detection you declare it AGAIN. You simply have to remove the "bool" before MonsterLeft (and all the other variables too), then you are just using it and not declaring it.

    edit: by the looks of your game you could consider using 2D in Unity or do you need the 3D?
     
    Food_Lover likes this.
  7. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    317
    Oh and one more thing, you can simplify your code a bit by combining the kill and the move part:

    if ( Input.GetKeyDown(KeyCode.LeftArrow) == true && BlockLeft == false ){
    transform.Translate(-1, 0, 0);
    if (MonsterLeft==true){
    Destroy(this);
    }
    }
     
    Food_Lover likes this.
  8. Food_Lover

    Food_Lover

    Joined:
    Dec 29, 2014
    Posts:
    16
    Ok Thanks I'll Look at it, also yes it's meant to be in 3D :)
     
  9. Food_Lover

    Food_Lover

    Joined:
    Dec 29, 2014
    Posts:
    16
    Ok Great News The Error's Are Gone :D Not so good news... It still dosn't work. Question, does there need to be a box collider on the object that I'm trying to detect? Well I no don't know what to do, if I have the collider on it will spaz out and go anywhere random (Like before), on the other hand if there's no collider then it goes right though. I changed my code accordingly and it works and is alot shorter (I'll add it below) , I added the tag which is the same as it is in the code & the move code works so it's something to do with the ray cast. (Sorry if that's a bad explanation) Code/Video Below:



    using UnityEngine;
    using System.Collections;

    public class Player_Movement : MonoBehaviour {

    public bool BlockLeft = false;
    public bool MonsterLeft = false;
    public bool BlockRight = false;
    public bool MonsterRight = false;
    public bool BlockForward = false;
    public bool MonsterForward = false;
    public bool BlockBack = false;
    public bool MonsterBack = false;
    void Update () {
    // Monster Detection
    RaycastHit hit;
    if ( Physics.Raycast (transform.position, Vector3.left, out hit, 1)) {
    if ( hit.transform.gameObject.tag == "Monster") {
    MonsterLeft = true;
    }
    }
    if ( Physics.Raycast (transform.position, Vector3.right, out hit, 1)) {
    if ( hit.transform.gameObject.tag == "Monster" ) {
    MonsterRight = true;
    }
    }
    if ( Physics.Raycast (transform.position, Vector3.forward, out hit, 1)) {
    if ( hit.transform.gameObject.tag == "Monster" ) {
    MonsterForward = true;
    }
    }
    if ( Physics.Raycast (transform.position, Vector3.back, out hit, 1)) {
    if ( hit.transform.gameObject.tag == "Monster" ) {
    MonsterBack = true;
    }
    }

    // Movement
    if ( Input.GetKeyDown(KeyCode.LeftArrow) == true && BlockLeft == false ){
    transform.Translate(-1, 0, 0);
    if (MonsterLeft==true){
    Destroy(this);
    }
    }
    if ( Input.GetKeyDown(KeyCode.RightArrow) == true && BlockRight == false ){
    transform.Translate(+1, 0, 0);
    if (MonsterRight==true){
    Destroy(this);
    }
    }
    if ( Input.GetKeyDown(KeyCode.UpArrow) == true && BlockForward == false ){
    transform.Translate(0, 0, +1);
    if (MonsterForward==true){
    Destroy(this);
    }
    }
    if ( Input.GetKeyDown(KeyCode.DownArrow) == true && BlockBack == false ){
    transform.Translate(0, 0, -1);
    if (MonsterBack==true){
    Destroy(this);
    }
    }
    }
    }
     
  10. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    317
    Hm my guess would be that your detection does not work. And I think this is because the ray you cast is too high, you cast it from the middle of the yellow player right? You can do one neat thing to show the ray you cast with Debug.DrawRay (http://docs.unity3d.com/ScriptReference/Debug.DrawRay.html) so in your example try Debug.DrawRay (transform.position, Vector3.left) in the Update. Then you can see in the editor where the player is "looking". Maybe Vector3.left is also wrong, maybe it has to be transform.forward, it depends how your player is rotated.
    But DrawRay will show you the way ;) I think you have to shoot the ray from the bottom of the player. And yes, you need the collider for the detection!
    One other way without any rays would be that you check all lasers as follows (pseudo code):
    tempPosition=player.position
    leftPosition=player.position+vector3(-1,0,0)
    for all lasers: laser.position==leftPosition? then: can not move

    But you have to watch out if the positions of the objects are really the same when you place them in the scene. You could also measure the distance from the desired player position and all lasers and if one distance is smaller than 1 then you can not move etc. Just a few ideas, but I think the rays should work best.

    Oh one idea more :) You can calculate the desired position and then use an overlap sphere (http://docs.unity3d.com/ScriptReference/Physics.OverlapSphere.html) to detect if there are lasers in the radius of the player.
     
    Food_Lover likes this.
  11. Food_Lover

    Food_Lover

    Joined:
    Dec 29, 2014
    Posts:
    16
    Ok, I now have it working! :D The problem was it was decting it but when you told to write destroy this, it was destroying the script not the object so were it says:
    if (MonsterBack==true){
    Destroy(this);
    }​

    I Wrote

    if (MonsterBack==true){
    Destroy(GameObect);
    }
    Thanks for all your help I probably would have given up if you didn't help me!
     
    Olipool likes this.
  12. Olipool

    Olipool

    Joined:
    Feb 8, 2015
    Posts:
    317
    Haha nice, that was easy, but hard to find :) Keep the spirit to go on until something works! :)
     
    Food_Lover likes this.