如何在不同的屏幕分辨率下拥有相同大小的对象?
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 中的布局
- 将
Rigidbody2D
和BoxCollider2D
全部添加
- 将他们的刚体设置为运动除了玩家
- 将此脚本添加到播放器
- 将墙标签设置为
Wall
- 将地面标记设置为
Ground
然后根据您的需要进行调整...
编辑:
你必须包含 transform.InverseTransformDirection(_body.velocity).x
和 Mathf.Abs()
才是正确的,而且有时碰撞法线会反转,使玩家卡在墙上,我让你想想这个:)
我正在使用 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 中的布局
- 将
Rigidbody2D
和BoxCollider2D
全部添加 - 将他们的刚体设置为运动除了玩家
- 将此脚本添加到播放器
- 将墙标签设置为
Wall
- 将地面标记设置为
Ground
然后根据您的需要进行调整...
编辑:
你必须包含 transform.InverseTransformDirection(_body.velocity).x
和 Mathf.Abs()
才是正确的,而且有时碰撞法线会反转,使玩家卡在墙上,我让你想想这个:)