问题描述
在 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 em>.
例如:如果您想创建一个正方形,您可以将其大小设置为绝对像素值或相对值(到父级)。如果您使用绝对值,则在 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;
}
}