Как остановить игрока от толкания NPC во время движения - PullRequest
0 голосов
/ 17 марта 2020

Моя проблема сегодня проста (две проблемы, если учесть тот факт, что Engli sh не является моим родным языком), но я не могу справиться с этим. Я пытаюсь сделать игру «вверх-вниз» в c#, и я пытаюсь улучшить сценарии движения, прежде чем работать над чем-то еще (поскольку я не хочу устранять серьезные ошибки позже).

проблема в том, что как только игрок входит в контакт с NP C, он должен перестать двигаться в своем общем направлении (он может двигаться в 8 направлениях, используя комбинации клавиш WASD). Движение NP C не доставляет никаких проблем, оно прекращает движение, как только воспринимает игрока. Вместо этого, когда игрок сталкивается с NP C, он продолжает двигаться в этом направлении, подталкивая его на полсекунды до остановки (как и должно быть). Итак, подводя итог, он не сразу останавливается, что нервирует, так как я много чего пытался остановить (включая замораживание позиции NP C, но это только ухудшило ситуацию).

Теперь коды:

Код движения NP C:

public class NPCFreeMovement : MonoBehaviour 
{
    public float speed = 2f;    //how fast does the npc move
    public float maxIdleTime = 3f; //max time the npc spends idling
    public float maxChooseTime = 20f;    //max time he spends moving
    public float chooseDirTime = 0; //if 0, he chooses a direction

    //possible directions
    readonly Vector3[] directions = {Vector3.down, new Vector3(-0.5f, -0.5f, 0), Vector3.left, new Vector3(-0.5f, 0.5f, 0), Vector3.up,
                            new Vector3(0.5f, 0.5f, 0), Vector3.right, new Vector3(0.5f, -0.5f, 0)};
    public int dir; //current direction

    public bool canMove = true; //pretty self explainatory
    public bool idle = true;    //is the npc idle
    public bool chase = false; //is the npc chasing after the player

    public Vector3 goTo;    //where to go if it's chasing after something

    void Start()
    {
        StartCoroutine(Idle(maxIdleTime));
    }

    void Update()
    {
        chase = GetComponent<NPCLookForPlayerScript>().found;


        if(canMove && !idle)
        {
            //move in the chosen direction
            transform.position = Vector3.MoveTowards(transform.position, transform.position + directions[dir], Time.deltaTime * speed);

            if (chooseDirTime > 0)  //decrease movement time
            {
                chooseDirTime -= Time.deltaTime;
            }
            else
            {
                if(chase)      StartCoroutine(Idle(0));
                else            StartCoroutine(Idle(Random.Range(0, maxIdleTime)));
            }
        }
    }

    //npc goes idle, then chooses a direction
    public IEnumerator Idle(float f)
    {
        idle = true;
        yield return new WaitForSeconds(f);
        idle = false;

        //here he chooses the direction depending of wether he's roaming or chasing
        if (chase)
        {
            ChooseDirection();
            chooseDirTime = maxChooseTime/4;
        }
        else
        {
            dir = Random.Range(0, directions.Length);
            chooseDirTime = maxChooseTime;
        }
    }

    //chooses a direction to take
    void ChooseDirection()
    {
        Vector3 v = goTo - transform.position;  //to check where to go
        if (Mathf.Abs(v.x) <= 0.5)
        {
            if (v.y < 0)    dir = 0;    //go down
            else            dir = 4;    //go up
        }
        if (Mathf.Abs(v.y) <= 0.5)
        {
            if (v.x < 0)    dir = 2;    //go left
            else            dir = 6;    //go right
        }
        if (v.x < 0.5 && v.y < 0.5) dir = 1;    //go down/left
        if (v.x < 0.5 && v.y > 0.5) dir = 3;    //go up/left
        if (v.x > 0.5 && v.y > 0.5) dir = 5;    //go up/right
        if (v.x > 0.5 && v.y < 0.5) dir = 7;    //go down/right
    }

    void OnCollisionEnter2D(Collision2D c)
    {
        if(c.gameObject.tag == "Obstacle")  //stop and choose a new direction
        {
            StartCoroutine(Idle(Random.Range(0, maxIdleTime)));
        }
        if (c.gameObject.tag == "Player")   //stop
        {
            canMove = false;
        }
    }

    private void OnCollisionExit2D(Collision2D c)
    {
        if (c.gameObject.tag == "Player")   //resume chasing the player
        {
            canMove = true;
        }
    }
}

Скрипт движения игрока:

public class PlayerFreeMovement : MonoBehaviour 
{
    public float speed = 2.0f; //movement speed

    //where he's facing
    public bool up;
    public bool down;
    public bool left;
    public bool right;

    public bool idle; //false if a movement button is pressed
    public bool canMove = true;

    //movement direction
    public float dx;
    public float dy;
    public Vector3 v;

    CollisionScript cs; //collision script

    void Start()
    {
        down = true;
        cs = GetComponent<CollisionScript>();
    }

    void Update()   //move stickman in the direction of the keys and maintain the direction he's facing with animations
    {
        dx = 0;
        dy = 0;

        if (!(Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S))) //check if idle
        {
            idle = true;
            v = new Vector3();
        }

        else    //the player's moving
        {
            idle = false;
            AllFalse();
            //set dx and dy
            if (canMove && Input.GetKey(KeyCode.D))
            {
                if(!cs.hitRight)     dx = 1;
                right = true;
            }
            if (canMove && Input.GetKey(KeyCode.A))
            {
                if (!cs.hitLeft)    dx = -1;
                left = true;
            }
            if (canMove && Input.GetKey(KeyCode.W))
            {
                if (!cs.hitUp)     dy = 1;
                up = true;
            }
            if (canMove && Input.GetKey(KeyCode.S))
            {
                if (!cs.hitDown)     dy = -1;
                down = true;
            }

            //create the motion vector
            v = new Vector3(dx, dy, 0);

            if(dx !=0 && dy != 0)
            {
                v = v / 2;
            }
        }
        //move
        transform.position = Vector3.MoveTowards(transform.position, transform.position + v, Time.deltaTime * speed);
    }

    //avoid bug by deactivating all direction booleans before changing one
    void AllFalse()
    {
        up = false;
        down = false;
        left = false;
        right = false;
    }
}

И, наконец, скрипт столкновения, используемый для обнаруживать столкновения на своем пути

public class CollisionScript: MonoBehaviour
{
    //where is the wall
    public bool hitDown= false;
    public bool hitLeft = false;
    public bool hitRight = false;
    public bool hitUp = false;

    //gizmos
    public float collisionRadius = 0.5f;
    public Vector2 downOffset = new Vector2(0, -0.5f);
    public Vector2 rightOffset = new Vector2(0, 0.5f);
    public Vector2 leftOffset = new Vector2(-0.5f, 0);
    public Vector2 upOffset = new Vector2(0, 0.5f);

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        hitDown = Physics2D.OverlapCircle((Vector2)transform.position + downOffset, collisionRadius).gameObject!=gameObject;
        hitRight = Physics2D.OverlapCircle((Vector2)transform.position + rightOffset, collisionRadius).gameObject != gameObject;
        hitLeft = Physics2D.OverlapCircle((Vector2)transform.position + leftOffset, collisionRadius).gameObject != gameObject;
        hitUp = Physics2D.OverlapCircle((Vector2)transform.position + upOffset, collisionRadius).gameObject != gameObject;
    }

    void OnDrawGizmos()
    {
        Gizmos.color = Color.red;

        Gizmos.DrawWireSphere((Vector2)transform.position + downOffset, collisionRadius);
        Gizmos.DrawWireSphere((Vector2)transform.position + rightOffset, collisionRadius);
        Gizmos.DrawWireSphere((Vector2)transform.position + leftOffset, collisionRadius);
        Gizmos.DrawWireSphere((Vector2)transform.position + upOffset, collisionRadius);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...