如何在不同的屏幕分辨率下拥有相同大小的对象?

How to have same size of objects in different screen resolutions?

我正在使用 Unity 开发 2D 游戏。我正在为 android 开发它,它处于纵向模式。我在屏幕左侧放置了一堵墙,在屏幕右侧放置了一堵墙。问题是这两堵墙之间的距离在不同的屏幕分辨率下是不同的。因此,我的角色无法以相同的速度从一堵墙跳到另一堵墙。 我附上一张图片来阐明我的观点。

我该怎么做才能在不同的设备上使这两堵墙之间的距离相同?任何帮助将不胜感激。

编辑:这就是我现在放置墙壁的方式。

screenLeft = Camera.main.ScreenToWorldPoint (new Vector3 (0f, 0f, 0f)).x;
screenRight = Camera.main.ScreenToWorldPoint (new Vector3 (Screen.width, 0f, 0f)).x;

rightWallSizeX = rightWall.GetComponent<SpriteRenderer> ().bounds.size.x;
leftWallSizeX = leftWall.GetComponent<SpriteRenderer> ().bounds.size.x;

rightWall.transform.position = new Vector3 (screenRight - rightWallSizeX/2, 0f, 0f);
leftWall.transform.position = new Vector3 (screenLeft + leftWallSizeX/2, 0f, 0f);

如果您使用编辑器设计关卡:

那么不管它的值是多少,输出方面都是正确的:

作为奖励,我为您编写了一些代码,让玩家可以粘在墙上并跳到墙的另一边 :D

using UnityEngine;

namespace Assets
{
    public class PlayerController : MonoBehaviour
    {
        private const string Ground = "Ground";
        private const string Wall = "Wall";

        private Rigidbody2D _body;
        private Vector2 _cNormal;
        private GameObject _cWall;
        private bool _joyAction;
        private float _joyClimb;
        private float _joyMove;
        private State _state;

        public float ForceClimb = 20.0f;
        public float ForceJump = 5.0f;
        public float ForceJumpFromWall = 10.0f;
        public float ForceMove = 10.0f;
        public float MaxMove = 15.0f;

        private void Start()
        {
            _state = State.Air;
        }

        private void OnEnable()
        {
            _body = GetComponent<Rigidbody2D>();
        }

        private void Update()
        {
            _joyMove = Input.GetAxis("Horizontal");
            _joyClimb = Input.GetAxis("Vertical");
            _joyAction = Input.GetButtonDown("Fire1");
        }

        private void FixedUpdate()
        {
            var air = _state == State.Air;
            var ground = _state == State.Ground;
            var wall = _state == State.Wall;

            if (air || ground)
            {
                var canJump = ground && _joyAction;
                if (canJump)
                {
                    var force = new Vector2(0.0f, ForceJump);
                    _body.AddForce(force, ForceMode2D.Impulse);
                    _state = State.Air;
                }

                var move = transform.InverseTransformDirection(_body.velocity).x;
                if (move < MaxMove)
                {
                    var force = new Vector2(_joyMove*ForceMove, 0.0f);
                    _body.AddRelativeForce(force);
                }
            }
            else if (wall)
            {
                var climbing = Mathf.Abs(_joyClimb) > 0.0f;
                if (climbing)
                {
                    _body.AddForce(new Vector2(0, ForceClimb*_joyClimb));
                }
                else
                {
                    var jumpingOut = _joyAction;
                    if (jumpingOut)
                    {
                        TryUnstickFromWall();
                        _body.AddForce(_cNormal*ForceJumpFromWall, ForceMode2D.Impulse);
                    }
                }
            }
        }

        private void OnGUI()
        {
            GUILayout.Label(_state.ToString());
        }

        public void OnCollisionEnter2D(Collision2D collision)
        {
            var c = collision.collider;
            var t = c.tag;
            if (t == Ground)
            {
                _state = State.Ground;
                TryUnstickFromWall(); // fixes wall-sticking
            }
            else if (t == Wall && _state == State.Air) // jumping to wall
            {
                var wall = collision.gameObject;
                var joint2D = wall.AddComponent<FixedJoint2D>();
                var contact = collision.contacts[0];
                var normal = contact.normal;
                Debug.DrawRay(contact.point, normal, Color.white);

                // stick 2 wall
                joint2D.anchor = contact.point;
                joint2D.frequency = 0.0f;
                joint2D.autoConfigureConnectedAnchor = false;
                joint2D.enableCollision = true;
                _body.constraints = RigidbodyConstraints2D.FreezePositionX;
                _body.gravityScale = 0.125f;

                // save these
                _cWall = wall;
                _cNormal = normal;

                // update state
                _state = State.Wall;
            }
        }

        public void OnCollisionExit2D(Collision2D collision)
        {
            if (collision.collider.tag == Ground)
            {
                _state = State.Air;
            }
        }

        private void TryUnstickFromWall()
        {
            if (_cWall != null)
            {
                _body.constraints = RigidbodyConstraints2D.None;
                _body.gravityScale = 1.0f;
                var joint2D = _cWall.GetComponent<FixedJoint2D>();
                if (joint2D != null) Destroy(joint2D);
                _cWall = null;
            }
        }
    }

    internal enum State
    {
        Air,
        Ground,
        Wall
    }
}

试一试:

  • 创建如图 1 中的布局
  • Rigidbody2DBoxCollider2D全部添加
  • 将他们的刚体设置为运动除了玩家
  • 将此脚本添加到播放器
  • 将墙标签设置为 Wall
  • 将地面标记设置为 Ground

然后根据您的需要进行调整...

编辑:

你必须包含 transform.InverseTransformDirection(_body.velocity).xMathf.Abs() 才是正确的,而且有时碰撞法线会反转,使玩家卡在墙上,我让你想想这个:)