unity3d - Unity 2D - 将播放器对象保持在其父面板的边界内
问题描述
在 Unity 中,我有一个 UI 面板,它有一个播放器对象(一个 UI 图像对象)。
我使用用户输入(键盘或触摸)将播放器对象移动到平面中
我不能将播放器对象保留在它的父面板中,
请检查下图,我想将播放器保留在红色面板内
这是我尝试过的代码
public Camera MainCamera; //be sure to assign this in the inspector to your main camera
private Vector2 screenBounds;
private float objectWidth;
private float objectHeight;
private RectTransform pnlBackgroundTransform;
private void Start()
{
pnlBackgroundTransform = GameObject.Find("PnlBackground").GetComponent<RectTransform>();
screenBounds = MainCamera.ScreenToWorldPoint(new Vector3(pnlBackgroundTransform.rect.width , pnlBackgroundTransform.rect.height , MainCamera.transform.position.z));
objectWidth = transform.GetComponent<SpriteRenderer>().bounds.extents.x; //extents = size of width / 2
objectHeight = transform.GetComponent<SpriteRenderer>().bounds.extents.y; //extents = size of height / 2
}
void LateUpdate()
{
Vector3 viewPos = transform.position;
viewPos.x = Mathf.Clamp(viewPos.x, screenBounds.x * -1 + objectWidth, screenBounds.x - objectWidth);
viewPos.y = Mathf.Clamp(viewPos.y, screenBounds.y * -1 + objectHeight, screenBounds.y - objectHeight);
Debug.Log(screenBounds);
Debug.Log(viewPos);
transform.position = viewPos;
}
解决方案
我想说将播放器实现为 UI 元素并不常见,相反,您应该在UI/Canvas
系统之外实现它。
该UI/Canvas
系统使用一组放置和缩放规则来处理响应式设计。你至少有 4 个值(不包括旋转)来在屏幕上放置一些东西:anchor、pivot、position和scale。
例如:如果您想创建一个正方形,您可以将其大小设置为绝对像素值或相对值(到父级)。如果您使用绝对值,UI Scale Mode
则在对象上定义的Canvas
应该会影响视觉结果。
这意味着UI/Canvas
应该适应屏幕的元素,例如按钮、对话框、标签等。利用设备参数来改善用户体验。
在UI/Canvas
系统之外,事物直接基于线性代数:您有一个 3D 向量空间(一个“世界”),其中所有事物都以绝对大小和位置存在。然后,您的相机会拉伸并扭曲整个世界,以匹配您当前的视角。这意味着无论屏幕大小如何,您的对象将始终具有相同的大小。
现在,假设您有一个非常具体的原因将您的游戏实现到 UI 中,您可以通过几种方法来实现。我假设您使用的是绝对值。请注意,这里使用的单位都是像素,对于不同分辨率的设备,效果应该是不同的,并且对UI Scale Mode
参数敏感。另外,请注意我已将锚点 min 和 max 都设置为 (0,0),左下角(默认为屏幕中心,(0.5,0.5)),以避免负坐标。
以下脚本附加到播放器的 UI 图像。
public class UIMovementController : MonoBehaviour
{
public float speed = 5.0f;
new private RectTransform transform;
private Rect canvasRect;
private void Start()
{
transform = GetComponent<RectTransform>();
canvasRect = GetComponentInParent<Canvas>().pixelRect;
}
void Update()
{
// Keyboard Input (Arrows)
Vector2 move = new Vector2(0,0);
if (Input.GetKey(KeyCode.UpArrow)) { move.y += speed; }
if (Input.GetKey(KeyCode.DownArrow)) { move.y -= speed; }
if (Input.GetKey(KeyCode.LeftArrow)) { move.x -= speed; }
if (Input.GetKey(KeyCode.RightArrow)) { move.x += speed; }
transform.anchoredPosition += move;
// Position clamping
Vector2 clamped = transform.anchoredPosition;
clamped.x = Mathf.Clamp(clamped.x, transform.rect.width / 2, canvasRect.width - transform.rect.width / 2);
clamped.y = Mathf.Clamp(clamped.y, transform.rect.height / 2, canvasRect.height - transform.rect.height / 2);
transform.anchoredPosition = clamped;
}
}
推荐阅读
- arrays - 从scala中的整数数组缓冲区中删除所有负元素
- python - (Flask API),让firebase上传的图片有唯一的名字
- javascript - 如何打乱用户添加的数组中的项目并显示结果?
- javascript - 如何在 JavaScript 中对 promise 的“then”结果进行单元测试?
- javascript - 如何使用 JavaScript 将表单数据发送到服务器
- random - 栅格堆栈上的随机点和提取值 500 次存储为列表
- java - Vertx hazelcast集群在重新加载更新的fat-jar时不稳定
- jquery - 在 jquery 上添加值时,我得到无穷大的数字
- azure-ad-b2c - URL 重定向不起作用 Android Azure B2C
- javascript - 图像滑块不滑动图像