Search code examples
unity-game-enginecollisionunity3d-2dtools

Unity: How to create a object on which can't teleport other object


how to create a 2D object on which can't teleport other (only stay on same position) object or can teleport only on one side (in picture left side). I have difficult and wrong way. Sorry for my English. There is project:

link 3

picture


Solution

  • With fixed steps movement ("jumping") you need code logic to determine if a certain movement is possible. I suggest creating a class for the target (red object) that has a variable that states which side is open and a function to see if you can enter from the side you are on.
    In your movement you need to check if such an object is in the direction you want to move to and ask it if you can enter from the side you are on.

    This is pretty pseudo since I don't know your grid implementation and how you determine where stuff is and can probably be optimized.

    public class Player : MonoBehaviour
    {
        void Update()
        {
            if("move to left" && "object on left".GetComponent<RedObject>().canEnterFromSide("right") == true)
            {
                //move
            }
            else if("move to right" && "object on right".GetComponent<RedObject>().canEnterFromSide("left") == true)
            {
                //move
            }
            else if("move to top" && "object on top".GetComponent<RedObject>().canEnterFromSide("bottom") == true)
            {
                //move
            }
            else if("move to bottom" && "object on bottom".GetComponent<RedObject>().canEnterFromSide("top") == true)
            {
                //move
            }            
        }
    }
    

    And place a script on the object (or add this to its script if it has one already) with something like this.

    public class RedObject : MonoBehaviour
    {
        // use e.g. "left", "right", "top", "bottom" to specify the open side
        // if you spawn the objects, set this upon spawning and according to the orientation obviously
        public string openSide = "left";
    
        public bool canEnterFromSide(string side)
        {
            return side == openSide;
        }
    }
    

    Update:
    Ok, I had a look into your project. Currently you don't have the part where you place the obstacles yet. This should be you next step.

    Create a generator that will spawn your obstacles a positions on your grid (the grid intervals would be your player speed. Have a list or dictionary that holds a reference to all your placed obstacles so you can refer to them. An easy way would be something like this:

    public class Generator : MonoBehaviour
    {
        public GameObject obstaclePrefab;
    
        Dictionary<string, GameObject> obstacles;    // Dictionary requires using System.Collections.Generic;
    
        // default rotation = open to the left
        Dictionary<string, Quaternion> rotations;
    
        void Start()
        {
            rotations = new Dictionary<string, Quaternion>()
            {
                { "left", Quaternion.Euler(0,0,0) },
                { "bottom", Quaternion.Euler(0,90,0) },
                { "right", Quaternion.Euler(0,180,0) },
                { "top", Quaternion.Euler(0,270,0) }
            }
        }
    
        void SpawnObstacle(Vector2 position, string openSide)
        {
            GameObject go = (GameObject)Instantiate(obstaclePrefab, position, rotations[openSide]);
            go.GetComponent<Obstacle>().openSide = openSide;
            string pos = position.x + "_" + position.y;
            obstacles.Add(pos, go);
        }
    
        GameObject GetObjectAt(Vector3 position)
        {
            string pos = position.x + "_" + position.y;
            if(obstacles.ContainsKey(pos) == true)
            {
                return obstacles[pos];
            }
            return null;
        }
    }
    

    Now if you move, ask this class if there is an obstacle at the desired destination. (I left out the other stuff from this class.)

    public class PlayerMove : MonoBehaviour { public int step;

    Generator generator;
    
    void Start()
    {
        generator = GameObject.FindWithTag("Generator");
    }
    
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.LeftArrow))
        {
            GameObject go = generator.GetObjectAt(transform.position - new Vector3(step, 0, 0));
            if(go == null || go.GetComponent<Obstacle>().CanEnterFromSide("right") == true)
            {
                transform.position = transform.position - new Vector3(step, 0, 0);
            }
        }
        // repeat for the other three directions.
    }
    

    }

    Now, this uses a fixed chess like grid where an obstacle occupies one cell. Your video shows some other behaviour, so this will probably not quite help you. It Easiest would probably be to either make the player move in a smooth motion and use colliders and rigidbodys like Programmer showed or to use a fixed grid like this would be.