Единство: проблема диагонального движения

У меня есть тестовая 2D-игра, в которой мой игрок двигался слева направо, и когда он доходил до конца экрана, он просто трансформировался на другой стороне. Я передумал и заставил игрока двигаться по диагонали. Это сработало, но я понятия не имею, как заставить игрока останавливаться, когда он достигает конца экрана. Я не хочу, чтобы это изменилось с другой стороны, а просто остановилось. Пока все мои результаты либо глючат по краям, либо вообще не останавливаются. Я предоставил свой сценарий PlayerController. Прямо сейчас мой игрок движется по диагонали, и он просто продолжит движение за край экрана. Если кто-нибудь может мне помочь, я был бы очень признателен. Никогда не думал, что займусь диагональным движением, но очень хочу научиться это делать.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class PlayerController : MonoBehaviour {

    public float speed = 7;
    public float speedy = 7;

    public event System.Action OnPlayerDeath;
    float screenHalfWidthInWorldUnits;
    Rigidbody2D rb;

    void Start () {
        rb = GetComponent<Rigidbody2D>();
        float halfPlayerWidth = transform.localScale.x / 2f;
        screenHalfWidthInWorldUnits = Camera.main.aspect * Camera.main.orthographicSize;
    }

    void Update()
    {
        float inputX = Input.GetAxisRaw("Horizontal");
        float velocity = inputX * speed;
        transform.Translate(Vector2.right * velocity * Time.deltaTime); 
    }


    public void MoveRight()
    {
        rb.velocity = new Vector2(speed, speedy);
    }

    public void MoveLeft()
    {
        rb.velocity = new Vector2(-speed, -speedy);
    }


    public void Stop()
    {
        rb.velocity =  Vector2.zero;
    }

    void OnTriggerEnter2D(Collider2D triggerCollider)
    {
        if (triggerCollider.tag =="Box")
        {
            if (OnPlayerDeath != null)
            {
                OnPlayerDeath();
            }
            Destroy(gameObject);
        }
    }
}

person TheNewbie    schedule 11.02.2018    source источник
comment
Вы хотите уничтожить игрока, когда дойдете до края?   -  person MGDroid    schedule 12.02.2018
comment
Почему бы просто не создать коллайдеры там, где вы хотите ограничить игрока?   -  person Ian H.    schedule 12.02.2018
comment
@MGDroid Нет, я просто хочу, чтобы он остановился. Он работал нормально, когда он был слева или справа, но с диагональю мне чего-то не хватает.   -  person TheNewbie    schedule 12.02.2018
comment
@IanH. Я связал. По какой-то причине я не мог сделать это правильно. Он снова работал при движении влево или вправо, но не по диагонали. Я подозреваю, что что-то с y.   -  person TheNewbie    schedule 12.02.2018
comment
Быстрый вопрос, почему вы перемещаете проигрыватель с помощью transform.Translate вместо использования ваших методов MoveRight() и MoveLeft()? (В настоящее время это игнорирует физические объекты, такие как коллайдеры.)   -  person Ian H.    schedule 12.02.2018
comment
@IanH. Я новичок в разработке игр, поэтому иногда я выбираю то, что работает. Тестовая игра - это мобильная игра, и у меня была проблема с сенсорным управлением при всех других методах программирования моих элементов управления. А теперь я хочу, чтобы мой игрок двигался по диагонали (положительно и отрицательно), но не могу заставить его остановиться на краю экрана. Один раз мне удалось заставить его попасть в край, но затем он просто перестал двигаться по диагонали и продолжил движение вверх, что полностью разрушило фиксированное позиционирование игрока.   -  person TheNewbie    schedule 12.02.2018
comment
@IanH. Любые возможные советы? Никогда не думал, что столкновение может стать проблемой. Я попробовал еще раз, и что бы я ни делал, столкновение не обнаруживается. Я добавил код, все пометил.   -  person TheNewbie    schedule 12.02.2018
comment
Можно ли добавить короткое видео / гифку о ситуации и проблеме? Мне сложно представить, что происходит.   -  person Ian H.    schedule 12.02.2018
comment
@IanH. we.tl/Y2FXBqg20w Я сделал очень короткое 18-мегабайтное видео. Загрузил на WeTransfer.   -  person TheNewbie    schedule 13.02.2018
comment
@MGDroid Есть какие-нибудь советы?   -  person TheNewbie    schedule 13.02.2018
comment
Я не могу увидеть, где находится ваша база кода проверки границ. В функции триггера вы сопоставили его с полем и пытаетесь уничтожить. Это коробка по диагонали? Вы в коробке и проверяете? Пожалуйста уточни   -  person MGDroid    schedule 13.02.2018
comment
@MGDroid У меня нет границ, потому что я не знаю, как их установить. У меня был ящик с тегом, который должен был столкнуться и остановить игрока, но он полностью его игнорирует.   -  person TheNewbie    schedule 13.02.2018


Ответы (1)


Вы можете проверить, находится ли игрок на той границе, которую вы определяете как границу карты.

Если вы проверите это для осей x и y соответственно, вы можете привязать его ось x или y к границе, а не дальше.

Вот пример написанного мной ранее сценария, который делает это.

Если я вас правильно понял, вы хотели бы двигаться по диагонали. В моем примере сценария ниже вы можете двигаться как по прямой, так и по диагонали, вы также можете деформировать края или останавливаться на краях, как вы говорили о желании.

Этот сценарий немного более продвинутый, чем то, что вам, вероятно, нужно, поэтому дайте мне знать, если что-то в нем вас смущает.

Обратите внимание, что если вы установите для логического _ShouldWarp значение false, он остановится на границе, в противном случае он будет деформироваться от края к краю карты.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{

    public float _Speed = 5f;
    public WorldBounds _WorldBounds;
    public bool _ShouldWarp; //If _ShouldWarp is false, will block players movement instead.

    void Update()
    {
        Move();
        WarpIfAtBoundary();
    }

    void Move()
    {
        float horizontal = Input.GetAxisRaw("Horizontal");
        float vertical = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.right * Time.deltaTime * _Speed * horizontal);
        transform.Translate(Vector3.up * Time.deltaTime * _Speed * vertical);
    }

    void WarpIfAtBoundary()
    {
        //X Axis
        //If player is at positive X boundary
        if (transform.position.x > (_WorldBounds.xPlus + _WorldBounds.xBuffer))
        {
            if (_ShouldWarp) //Teleport/warp player is set to enabled
            {
                transform.position = new Vector3(_WorldBounds.xMinus, transform.position.y, transform.position.z);
            }
            else //Otherwise keep player in border position
            {
                transform.position = new Vector3(_WorldBounds.xPlus + _WorldBounds.xBuffer, transform.position.y, transform.position.z);
            }
        }
        //Else if player is at negative X boundary
        else if (transform.position.x < (_WorldBounds.xMinus - _WorldBounds.xBuffer))
        {
            if (_ShouldWarp)//Teleport/warp player is set to enabled
            {
                transform.position = new Vector3(_WorldBounds.xPlus, transform.position.y, transform.position.z);
            }
            else //Otherwise keep player in border position
            {
                transform.position = new Vector3(_WorldBounds.xMinus - _WorldBounds.xBuffer, transform.position.y, transform.position.z);
            }
        }

        //Y Axis
        //If player is at positive Y boundary
        if (transform.position.y > (_WorldBounds.yPlus + _WorldBounds.yBuffer))
        {
            if (_ShouldWarp)//Teleport/warp player is set to enabled
            {
                transform.position = new Vector3(transform.position.x, _WorldBounds.yMinus, transform.position.z);
            }
            else //Otherwise keep player in border position
            {
                transform.position = new Vector3(transform.position.x, _WorldBounds.yPlus + _WorldBounds.yBuffer, transform.position.z);
            }
        }
        //Else if player is at negative Y boundary
        else if (transform.position.y < (_WorldBounds.yMinus - _WorldBounds.yBuffer))
        {
            if (_ShouldWarp)//Teleport/warp player is set to enabled
            { 
                transform.position = new Vector3(transform.position.x, _WorldBounds.yPlus, transform.position.z);
            }
            else //Otherwise keep player in border position
            {
                transform.position = new Vector3(transform.position.x, _WorldBounds.yMinus - _WorldBounds.yBuffer, transform.position.z);
            }
        }
    }
}

//Set as serializable so it displays correctly in Unity's inspector window.
[System.Serializable]
public class WorldBounds
{
    [Header("Bounds")]
    public float xMinus = -9.4f;
    public float xPlus = 9.4f;
    public float yMinus = -9.4f;
    public float yPlus = 9.4f;
    [Header("BufferZone")]
    public float xBuffer = 1f;
    public float yBuffer = 1f;
}

РЕДАКТИРОВАТЬ:

С вашими дополнениями я смогу назначить движение двум моим кнопкам. Один вверх и вправо, а другой внизу и влево.

        void Move()
    {
        float horizontal = Input.GetAxisRaw("Horizontal");
        transform.Translate(Vector3.right * Time.deltaTime * _Speed * horizontal);
        transform.Translate(Vector3.up * Time.deltaTime * _Speed * horizontal);
    }

Это должно работать, чтобы двигаться по диагонали влево и вниз, а также вверх и вправо.

Я сделал изменение, чтобы использовать горизонтальный вход для движения как по оси X, так и по оси Y.

Мне не нужен варп. Просто ступить на определенные границы

Вы можете установить логическое значение Warp в значение false или удалить части деформации из кода, тогда :-), должно работать.

person Doh09    schedule 12.02.2018
comment
Единственное, прежде чем я попробую это реализовать. С вашими дополнениями я смогу назначить движение двум моим кнопкам. Один вверх и вправо, а другой внизу и влево. Просто общий вопрос, потому что я вполне могу облажаться. - person TheNewbie; 13.02.2018
comment
Из того, что я вижу. Мне не нужен варп. Просто перешагнуть обозначенные границы. Не знаю как, но попробую. Что-то с добавлением границ к моим позициям x и y. Также на заметку. Я не хочу, чтобы он двигался прямо. Только правая верхняя диагональ и нижняя левая диагональная линия. - person TheNewbie; 13.02.2018
comment
Пожалуйста, посмотрите правку, которую я только что внес в конец исходного ответа, где я пытаюсь ответить на ваш вопрос. - person Doh09; 13.02.2018
comment
Две небольшие проблемы. Я не уверен, как назначить функцию Move () двум кнопкам вверх / вправо и вниз / влево в инспекторе. Теперь работает с клавиатурой. Во-вторых, не могли бы вы дать мне совет по поводу масштабирования границ? Прямо сейчас мой игрок попадает в границу, но она слишком велика, и если я что-то изменяю в буфере или ограничиваю, то место появления перемещается для моего игрока, и поэтому я никогда не смогу правильно настроить границы. Спасибо! - person TheNewbie; 14.02.2018
comment
Для ввода в код я использую систему ввода Unity, в данном случае то, что называется горизонтальной осью. Обычно этим можно управлять с помощью кнопок A и D или клавиш со стрелками влево и вправо. Страница документации о вводе: docs.unity3d.com/ScriptReference/Input.html Для масштабирования границы, переместите игрока ближе к границе, посмотрите, каковы его координаты, а затем примените эту координату к переменной Bounds. Не уверен, что вы имеете в виду под изменением места возрождения, это не должно влиять на место возрождения. - person Doh09; 14.02.2018
comment
Вам может быть полезно посмотреть эту серию видеоуроков по созданию игры: youtube.com/ В учебнике 9 видео с подробным объяснением. Для новичка может быть полезно учиться таким образом. - person Doh09; 14.02.2018
comment
Спасибо! Границы удалось определить. Осталось только то, что я до сих пор не знаю, как разделить код на две отдельные кнопки. Некоторое время назад я делал учебник, и они тоже использовали систему ввода Unity, но я нигде не могу найти, как превратить ее в две кнопки в игре вместо клавиш клавиатуры. - person TheNewbie; 14.02.2018
comment
Вы можете сделать переменную типа Keycode. Так, например: Public Keycode moveLeft; Открытый ключевой код moveRight; Затем вы можете сделать эти кнопки в Инспекторе определенной кнопкой. Тогда класс Input может сказать float direction = 0f; если (Input.GetKey (moveLeft)) {направление = -1f; } иначе, если (Input.GetKey (moveLeft)) {direction = 1f; } Затем просто используйте переменную направления вместо горизонтальной переменной. - person Doh09; 14.02.2018
comment
Давайте продолжим это обсуждение в чате. - person Doh09; 14.02.2018
comment
Конечно, это возможно. Это то, что я только что сделал с примером Keycode. Но, пожалуйста, войдите в чат, который я начал, на него есть ссылка в предыдущем моем комментарии. - person Doh09; 14.02.2018