【问题标题】:How to have same size of objects in different screen resolutions?如何在不同的屏幕分辨率下拥有相同大小的对象?
【发布时间】:2016-06-17 23:46:33
【问题描述】:

我正在使用 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);

【问题讨论】:

  • 这是 Sprite 还是 ui 组件?
  • 这些是精灵。
  • 将墙放置在屏幕侧面旁边是错误的,因为它们是“相对”放置的……您应该以“绝对”的方式放置它们,即您的关卡设计应该是独一无二的,无论如何使用屏幕尺寸。提示:发布一些代码
  • 如果您希望根据屏幕比例获得“动态”设计级别,另一种方法是将光线从玩家位置投射到另一面墙上,命中距离将为您提供有关玩家跳出到达另一边的必要力量。
  • @Aybe 添加了一些代码。你能指导我这里最好的方法是什么吗?

标签: unity3d unity3d-2dtools


【解决方案1】:

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

那么无论其值如何,输出方面都是正确的:

作为奖励,我已经为你制作了一些代码,让玩家可以粘在墙上并跳到它的另一边: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() 结合起来才能正确,有时碰撞法线会被反转,使玩家粘在墙上,我让你算出这个:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    相关资源
    最近更新 更多