unity3d (2d!) - 相机以玩家为中心,但永远不会超过 "map" 边界
unity3d (2d!) - Camera to centre on player, but never exceed "map" bounds
我正在创建一个最多有 4 个正交摄像机(最多 4 个玩家)的游戏,它们占据不同数量的屏幕,具体取决于玩家数量。
我有一个脚本可以控制所有摄像机,设置它们相对于正在观看的玩家的位置。
我想要实现的是一种简单的 overhead-runner 移动方式,即摄像机将跟随玩家,但不会超出地图范围。
当摄像机为 'square'(如在 4 人布局中)时,我已经设法让边界在 top-left 摄像机中工作。然而,其他摄像机根本无法正确跟踪,在矩形 2 人模式下,顶部摄像机仍然走得太远 left-and 对。我很确定我确切地知道是哪一行代码导致了这个问题...但是我不知道我需要做什么来修复它...
SpriteRenderer spriteBounds = GameObject.Find("Map").GetComponentInChildren<SpriteRenderer>();
float leftBound =0;
float rightBound =0;
float bottomBound =0;
float topBound = 0;
if((trackPlayer1 == null))
{
camPlayer1.transform.position = this.transform.position;
}
else
{
float vertExtent = camPlayer1.orthographicSize;
float horzExtent = vertExtent * Screen.width / Screen.height; //I guess the problem is here... but how do I fix this??
leftBound = (float)(horzExtent - spriteBounds.sprite.bounds.size.x / 2.0f);
rightBound = (float)(spriteBounds.sprite.bounds.size.x / 2.0f - horzExtent);
bottomBound = (float)(vertExtent - spriteBounds.sprite.bounds.size.y / 2.0f);
topBound = (float)(spriteBounds.sprite.bounds.size.y / 2.0f - vertExtent);
camPlayer1.transform.position = new Vector3(Mathf.Clamp(trackPlayer1.transform.position.x, leftBound, rightBound), Mathf.Clamp(trackPlayer1.transform.position.y, bottomBound, topBound), camPlayer1.transform.position.z);
}
if((trackPlayer2 == null))
{
camPlayer2.transform.position = this.transform.position;
}
else
{
float vertExtent = camPlayer2.orthographicSize ;
float horzExtent = vertExtent * Screen.width / Screen.height; //I guess the problem is here... but how do I fix this??
leftBound = (float)(horzExtent - spriteBounds.sprite.bounds.size.x / 2.0f);
rightBound = (float)(spriteBounds.sprite.bounds.size.x / 2.0f - horzExtent);
bottomBound = (float)(vertExtent - spriteBounds.sprite.bounds.size.y / 2.0f);
topBound = (float)(spriteBounds.sprite.bounds.size.y / 2.0f - vertExtent);
camPlayer2.transform.position = new Vector3(Mathf.Clamp(trackPlayer2.transform.position.x, leftBound, rightBound), Mathf.Clamp(trackPlayer2.transform.position.y, topBound, bottomBound), camPlayer2.transform.position.z);
}
if((trackPlayer3 == null))
{
camPlayer3.transform.position = this.transform.position;
}
else
{
float vertExtent = camPlayer3.orthographicSize;
float horzExtent = vertExtent * Screen.width / Screen.height; //I guess the problem is here... but how do I fix this??
leftBound = (float)(horzExtent - spriteBounds.sprite.bounds.size.x / 2.0f);
rightBound = (float)(spriteBounds.sprite.bounds.size.x / 2.0f - horzExtent);
bottomBound = (float)(vertExtent - spriteBounds.sprite.bounds.size.y / 2.0f);
topBound = (float)(spriteBounds.sprite.bounds.size.y / 2.0f - vertExtent);
camPlayer3.transform.position = new Vector3(Mathf.Clamp(trackPlayer3.transform.position.x, leftBound, rightBound), Mathf.Clamp(trackPlayer3.transform.position.y, topBound, bottomBound), camPlayer3.transform.position.z);
}
if((trackPlayer4 == null))
{
camPlayer4.transform.position = this.transform.position;
}
else
{
float vertExtent = camPlayer4.orthographicSize;
float horzExtent = vertExtent * Screen.width / Screen.height; //I guess the problem is here... but how do I fix this??
leftBound = (float)(horzExtent - spriteBounds.sprite.bounds.size.x / 2.0f);
rightBound = (float)(spriteBounds.sprite.bounds.size.x / 2.0f - horzExtent);
bottomBound = (float)(vertExtent - spriteBounds.sprite.bounds.size.y / 2.0f);
topBound = (float)(spriteBounds.sprite.bounds.size.y / 2.0f - vertExtent);
camPlayer4.transform.position = new Vector3(Mathf.Clamp(trackPlayer4.transform.position.x, leftBound, rightBound), Mathf.Clamp(trackPlayer4.transform.position.y, topBound, bottomBound), camPlayer4.transform.position.z);
}
所以我很确定我需要检查相机尺寸和屏幕上的相对位置,但我不知道我需要做什么。
(编辑)
脚本解释:
- 脚本是附加到主相机对象的全局脚本,玩家永远看不到
- 四个播放器摄像头 (camPlayer1 - camPlayer4) 是 public 变量并分配给设计器中的脚本
- trackPlayer1-trackPlayer4 是 public 个游戏对象,它们在设计器中分配 - 它们被分配给玩家对象
- 玩家跟踪适用于所有摄像头...例如,如果我更改 camPlayer2.transform.position = new Vector3(Mathf.Clamp(trackPlayer2.transform.position.x, leftBound, rightBound), Mathf.Clamp(trackPlayer2.transform.position.y, topBound, bottomBound), camPlayer2.transform.position.z); 到 camPlayer2.transform.position = trackPlayer2.transform.position;,代码达到预期效果,摄像机跟随玩家。我遇到的问题只是限制在地图的边界上
- 相机的正交尺寸设置为 2
启动时在屏幕上定位相机的代码:
switch (playerCount)
{
case 1:
camPlayer1.enabled = true;
camPlayer2.enabled = false;
camPlayer3.enabled = false;
camPlayer4.enabled = false;
camPlayer1.rect = new Rect(0, 0, 1, 1);
camPlayer1.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer2.rect = new Rect(0, 0, 0, 0);
camPlayer2.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer3.rect = new Rect(0, 0, 0, 0);
camPlayer3.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer4.rect = new Rect(0, 0, 0, 0);
camPlayer4.orthographicSize = CamManager.CAMERA_SIZE;
break;
case 2:
camPlayer1.enabled = true;
camPlayer2.enabled = true;
camPlayer3.enabled = false;
camPlayer4.enabled = false;
camPlayer1.rect = new Rect(0, 0.5f, 0.7f, 0.5f);
camPlayer1.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer2.rect = new Rect(0.3f, 0, 0.7f, 0.5f);
camPlayer2.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer3.rect = new Rect(0, 0, 0, 0);
camPlayer3.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer4.rect = new Rect(0, 0, 0, 0);
camPlayer4.orthographicSize = CamManager.CAMERA_SIZE;
Destroy(play3);
Destroy(play4);
break;
case 3:
camPlayer1.enabled = true;
camPlayer2.enabled = true;
camPlayer3.enabled = true;
camPlayer4.enabled = false;
camPlayer1.rect = new Rect(0, 0.5f, 0.5f, 0.5f);
camPlayer1.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer2.rect = new Rect(0.5f, 0.5f, 0.5f, 0.5f);
camPlayer2.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer3.rect = new Rect(0.25f, 0, 0.5f, 0.5f);
camPlayer3.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer4.rect = new Rect(0, 0, 0, 0);
camPlayer4.orthographicSize = CamManager.CAMERA_SIZE;
Destroy(play4);
break;
case 4:
camPlayer1.enabled = true;
camPlayer2.enabled = true;
camPlayer3.enabled = true;
camPlayer4.enabled = true;
camPlayer1.rect = new Rect(0, 0.5f, 0.5f, 0.5f);
camPlayer1.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer2.rect = new Rect(0.5f, 0.5f, 0.5f, 0.5f);
camPlayer2.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer3.rect = new Rect(0, 0, 0.5f, 0.5f);
camPlayer3.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer4.rect = new Rect(0.5f, 0, 0.5f, 0.5f);
camPlayer4.orthographicSize = CamManager.CAMERA_SIZE;
break;
}
}
编辑,这样我就可以使用下面的代码让第一个摄像机不受形状影响(因此在 2 人模式下,使用矩形摄像机,玩家 1 摄像机将遵守地图的边界)。我猜想我需要根据其他凸轮的矩形对 leftBound、rightBound、topBound 和 bottomBound 应用一些偏移量。如何建立和计算这些我不知道
if((trackPlayer1 == null))
{
camPlayer1.transform.position = this.transform.position;
}
else
{
float vertExtent = camPlayer1.orthographicSize;
float horzExtent = vertExtent * (Screen.width * (camPlayer1.rect.width * 2)) / Screen.height; //I guess the problem is here... but how do I fix this??
我想建议您使用另一种方法来解决您的问题。
是否可以在地图的边界处添加高碰撞器,并为相机添加碰撞器?然后你可以让相机跟随玩家(使用物理!),当玩家到达边界时,由于碰撞器,相机不会越过。
然后,您可以轻松地分割屏幕,知道您有多少玩家。
一名球员? --> 所有屏幕尺寸
两名球员? --> camera 1 ends ad screen height / 2, camera 2 starts at screen heigth /2 +1
等等
你的计算有几个问题。我想这只是运气,它适用于某些情况。虽然您的总体想法是正确的,但您正在使用错误的属性进行计算。基本上,您需要了解相机的纵横比、地图的边界框以及相机在边界处的行为方式。
我们需要相机的宽高比来计算它的宽度或范围。
如图所示,Screen.width
和 Screen.height
是指游戏的 window 或显示器分辨率,如果您是 运行 游戏全屏。您还可以看到,与游戏相比,相机的纵横比可能不同 window。好消息是Unity提供了一个属性来获取相机的长宽比
float camVertExtent = cam.orthograpicSize;
float camHorzExtent = cam.aspect * camVertExtent;
现在我们有了相机的范围,让我们看一下您的地图及其边界框。
您尝试使用 bounds.size
计算,但如您所见,bounds.size.x
是边界框的宽度。仅当您的地图 bottom-left 在世界 space 中从 (0,0) 开始时,使用该大小才有效。更好的方法是使用 bounds.min
和 bounds.max
,它们已经 return 坐标在世界 space.
你的最终目标是相机应该在地图的范围内,即它的位置受到以下四个条件的限制:
(cam.transform.position.x - camHorzExtent) >= bounds.min.x // left
(cam.transform.position.x + camHorzExtent) <= bounds.max.x // right
(cam.transform.position.y - camVertExtent) >= bounds.min.y // bottom
(cam.transform.position.y + camVertExtent) <= bounds.max.y // top
现在你只需要获取玩家位置并将相机限制在这些条件下:
float leftBound = bounds.min.x + camHorzExtent;
float rightBound = bounds.max.x - camHorzExtent;
float bottomBound = bounds.min.y + camVertExtent;
float topBound = bounds.max.y - camVertExtent;
float camX = Mathf.Clamp(player.transform.position.x, leftBound, rightBound);
float camY = Mathf.Clamp(player.transform.position.y, bottomBound, topBound);
cam.transform.position = new Vector3(camX, camY, cam.transform.position.z);
如果所有摄像机的尺寸和纵横比都相同,您可以对所有玩家摄像机使用相同的边界,并且只为每个玩家计算 camX
和 camY
。
你应该使用这个简单但有用的东西unity 2d camera follow script
也可在 github 上使用。
https://gist.github.com/unity3diy/5aa0b098cb06b3ccbe47
using UnityEngine;
using System.Collections;
public class FollowCamera : MonoBehaviour {
public float interpVelocity;
public float minDistance;
public float followDistance;
public GameObject target;
public Vector3 offset;
Vector3 targetPos;
// Use this for initialization
void Start () {
targetPos = transform.position;
}
// Update is called once per frame
void FixedUpdate () {
if (target)
{
Vector3 posNoZ = transform.position;
posNoZ.z = target.transform.position.z;
Vector3 targetDirection = (target.transform.position - posNoZ);
interpVelocity = targetDirection.magnitude * 5f;
targetPos = transform.position + (targetDirection.normalized * interpVelocity * Time.deltaTime);
transform.position = Vector3.Lerp( transform.position, targetPos + offset, 0.25f);
}
}
}
大家好,有些人需要完整的代码才能将许多儿童精灵转换为空游戏对象,例如:
Background
--mountains1(sprite)
--mountains2(sprite)
--mountains3(sprite)
这段代码将循环到背景对象中,并绑定所有儿童精灵 :D,感谢@Stefan Hoffmann 的解释,我制作了一个 Frankestein 代码哈哈。我希望这对其他人有帮助,抱歉我的英语不好:(
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
private float rightBound;
private float leftBound;
private float topBound;
private float bottomBound;
private Vector3 pos;
private Transform target;
private Camera cam;
private Bounds bounds;
// Use this for initialization
void Start()
{
target = GameObject.FindWithTag("Player").transform;
foreach (SpriteRenderer spriteBounds in GameObject.Find("Background").GetComponentsInChildren<SpriteRenderer>())
{
bounds.Encapsulate(spriteBounds.bounds);
}
cam = this.gameObject.GetComponent<Camera>();
float camVertExtent = cam.orthographicSize;
float camHorzExtent = cam.aspect * camVertExtent;
Debug.Log(camVertExtent);
Debug.Log(camHorzExtent);
Debug.Log(cam.aspect);
Debug.Log(cam.orthographicSize);
leftBound = bounds.min.x + camHorzExtent;
rightBound = bounds.max.x - camHorzExtent;
bottomBound = bounds.min.y + camVertExtent;
topBound = bounds.max.y - camVertExtent;
Debug.Log("leftBound=" + leftBound);
Debug.Log("rightBound=" + rightBound);
Debug.Log("bottomBound=" + bottomBound);
Debug.Log("topBound=" + topBound);
}
// Update is called once per frame
void Update()
{
float camX = Mathf.Clamp(target.transform.position.x, leftBound, rightBound);
float camY = Mathf.Clamp(target.transform.position.y, bottomBound, topBound);
cam.transform.position = new Vector3(camX, camY, cam.transform.position.z);
}
}
我正在创建一个最多有 4 个正交摄像机(最多 4 个玩家)的游戏,它们占据不同数量的屏幕,具体取决于玩家数量。
我有一个脚本可以控制所有摄像机,设置它们相对于正在观看的玩家的位置。
我想要实现的是一种简单的 overhead-runner 移动方式,即摄像机将跟随玩家,但不会超出地图范围。
当摄像机为 'square'(如在 4 人布局中)时,我已经设法让边界在 top-left 摄像机中工作。然而,其他摄像机根本无法正确跟踪,在矩形 2 人模式下,顶部摄像机仍然走得太远 left-and 对。我很确定我确切地知道是哪一行代码导致了这个问题...但是我不知道我需要做什么来修复它...
SpriteRenderer spriteBounds = GameObject.Find("Map").GetComponentInChildren<SpriteRenderer>();
float leftBound =0;
float rightBound =0;
float bottomBound =0;
float topBound = 0;
if((trackPlayer1 == null))
{
camPlayer1.transform.position = this.transform.position;
}
else
{
float vertExtent = camPlayer1.orthographicSize;
float horzExtent = vertExtent * Screen.width / Screen.height; //I guess the problem is here... but how do I fix this??
leftBound = (float)(horzExtent - spriteBounds.sprite.bounds.size.x / 2.0f);
rightBound = (float)(spriteBounds.sprite.bounds.size.x / 2.0f - horzExtent);
bottomBound = (float)(vertExtent - spriteBounds.sprite.bounds.size.y / 2.0f);
topBound = (float)(spriteBounds.sprite.bounds.size.y / 2.0f - vertExtent);
camPlayer1.transform.position = new Vector3(Mathf.Clamp(trackPlayer1.transform.position.x, leftBound, rightBound), Mathf.Clamp(trackPlayer1.transform.position.y, bottomBound, topBound), camPlayer1.transform.position.z);
}
if((trackPlayer2 == null))
{
camPlayer2.transform.position = this.transform.position;
}
else
{
float vertExtent = camPlayer2.orthographicSize ;
float horzExtent = vertExtent * Screen.width / Screen.height; //I guess the problem is here... but how do I fix this??
leftBound = (float)(horzExtent - spriteBounds.sprite.bounds.size.x / 2.0f);
rightBound = (float)(spriteBounds.sprite.bounds.size.x / 2.0f - horzExtent);
bottomBound = (float)(vertExtent - spriteBounds.sprite.bounds.size.y / 2.0f);
topBound = (float)(spriteBounds.sprite.bounds.size.y / 2.0f - vertExtent);
camPlayer2.transform.position = new Vector3(Mathf.Clamp(trackPlayer2.transform.position.x, leftBound, rightBound), Mathf.Clamp(trackPlayer2.transform.position.y, topBound, bottomBound), camPlayer2.transform.position.z);
}
if((trackPlayer3 == null))
{
camPlayer3.transform.position = this.transform.position;
}
else
{
float vertExtent = camPlayer3.orthographicSize;
float horzExtent = vertExtent * Screen.width / Screen.height; //I guess the problem is here... but how do I fix this??
leftBound = (float)(horzExtent - spriteBounds.sprite.bounds.size.x / 2.0f);
rightBound = (float)(spriteBounds.sprite.bounds.size.x / 2.0f - horzExtent);
bottomBound = (float)(vertExtent - spriteBounds.sprite.bounds.size.y / 2.0f);
topBound = (float)(spriteBounds.sprite.bounds.size.y / 2.0f - vertExtent);
camPlayer3.transform.position = new Vector3(Mathf.Clamp(trackPlayer3.transform.position.x, leftBound, rightBound), Mathf.Clamp(trackPlayer3.transform.position.y, topBound, bottomBound), camPlayer3.transform.position.z);
}
if((trackPlayer4 == null))
{
camPlayer4.transform.position = this.transform.position;
}
else
{
float vertExtent = camPlayer4.orthographicSize;
float horzExtent = vertExtent * Screen.width / Screen.height; //I guess the problem is here... but how do I fix this??
leftBound = (float)(horzExtent - spriteBounds.sprite.bounds.size.x / 2.0f);
rightBound = (float)(spriteBounds.sprite.bounds.size.x / 2.0f - horzExtent);
bottomBound = (float)(vertExtent - spriteBounds.sprite.bounds.size.y / 2.0f);
topBound = (float)(spriteBounds.sprite.bounds.size.y / 2.0f - vertExtent);
camPlayer4.transform.position = new Vector3(Mathf.Clamp(trackPlayer4.transform.position.x, leftBound, rightBound), Mathf.Clamp(trackPlayer4.transform.position.y, topBound, bottomBound), camPlayer4.transform.position.z);
}
所以我很确定我需要检查相机尺寸和屏幕上的相对位置,但我不知道我需要做什么。
(编辑) 脚本解释:
- 脚本是附加到主相机对象的全局脚本,玩家永远看不到
- 四个播放器摄像头 (camPlayer1 - camPlayer4) 是 public 变量并分配给设计器中的脚本
- trackPlayer1-trackPlayer4 是 public 个游戏对象,它们在设计器中分配 - 它们被分配给玩家对象
- 玩家跟踪适用于所有摄像头...例如,如果我更改 camPlayer2.transform.position = new Vector3(Mathf.Clamp(trackPlayer2.transform.position.x, leftBound, rightBound), Mathf.Clamp(trackPlayer2.transform.position.y, topBound, bottomBound), camPlayer2.transform.position.z); 到 camPlayer2.transform.position = trackPlayer2.transform.position;,代码达到预期效果,摄像机跟随玩家。我遇到的问题只是限制在地图的边界上
- 相机的正交尺寸设置为 2
启动时在屏幕上定位相机的代码:
switch (playerCount)
{
case 1:
camPlayer1.enabled = true;
camPlayer2.enabled = false;
camPlayer3.enabled = false;
camPlayer4.enabled = false;
camPlayer1.rect = new Rect(0, 0, 1, 1);
camPlayer1.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer2.rect = new Rect(0, 0, 0, 0);
camPlayer2.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer3.rect = new Rect(0, 0, 0, 0);
camPlayer3.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer4.rect = new Rect(0, 0, 0, 0);
camPlayer4.orthographicSize = CamManager.CAMERA_SIZE;
break;
case 2:
camPlayer1.enabled = true;
camPlayer2.enabled = true;
camPlayer3.enabled = false;
camPlayer4.enabled = false;
camPlayer1.rect = new Rect(0, 0.5f, 0.7f, 0.5f);
camPlayer1.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer2.rect = new Rect(0.3f, 0, 0.7f, 0.5f);
camPlayer2.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer3.rect = new Rect(0, 0, 0, 0);
camPlayer3.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer4.rect = new Rect(0, 0, 0, 0);
camPlayer4.orthographicSize = CamManager.CAMERA_SIZE;
Destroy(play3);
Destroy(play4);
break;
case 3:
camPlayer1.enabled = true;
camPlayer2.enabled = true;
camPlayer3.enabled = true;
camPlayer4.enabled = false;
camPlayer1.rect = new Rect(0, 0.5f, 0.5f, 0.5f);
camPlayer1.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer2.rect = new Rect(0.5f, 0.5f, 0.5f, 0.5f);
camPlayer2.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer3.rect = new Rect(0.25f, 0, 0.5f, 0.5f);
camPlayer3.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer4.rect = new Rect(0, 0, 0, 0);
camPlayer4.orthographicSize = CamManager.CAMERA_SIZE;
Destroy(play4);
break;
case 4:
camPlayer1.enabled = true;
camPlayer2.enabled = true;
camPlayer3.enabled = true;
camPlayer4.enabled = true;
camPlayer1.rect = new Rect(0, 0.5f, 0.5f, 0.5f);
camPlayer1.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer2.rect = new Rect(0.5f, 0.5f, 0.5f, 0.5f);
camPlayer2.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer3.rect = new Rect(0, 0, 0.5f, 0.5f);
camPlayer3.orthographicSize = CamManager.CAMERA_SIZE;
camPlayer4.rect = new Rect(0.5f, 0, 0.5f, 0.5f);
camPlayer4.orthographicSize = CamManager.CAMERA_SIZE;
break;
}
}
编辑,这样我就可以使用下面的代码让第一个摄像机不受形状影响(因此在 2 人模式下,使用矩形摄像机,玩家 1 摄像机将遵守地图的边界)。我猜想我需要根据其他凸轮的矩形对 leftBound、rightBound、topBound 和 bottomBound 应用一些偏移量。如何建立和计算这些我不知道
if((trackPlayer1 == null))
{
camPlayer1.transform.position = this.transform.position;
}
else
{
float vertExtent = camPlayer1.orthographicSize;
float horzExtent = vertExtent * (Screen.width * (camPlayer1.rect.width * 2)) / Screen.height; //I guess the problem is here... but how do I fix this??
我想建议您使用另一种方法来解决您的问题。
是否可以在地图的边界处添加高碰撞器,并为相机添加碰撞器?然后你可以让相机跟随玩家(使用物理!),当玩家到达边界时,由于碰撞器,相机不会越过。
然后,您可以轻松地分割屏幕,知道您有多少玩家。 一名球员? --> 所有屏幕尺寸 两名球员? --> camera 1 ends ad screen height / 2, camera 2 starts at screen heigth /2 +1 等等
你的计算有几个问题。我想这只是运气,它适用于某些情况。虽然您的总体想法是正确的,但您正在使用错误的属性进行计算。基本上,您需要了解相机的纵横比、地图的边界框以及相机在边界处的行为方式。
我们需要相机的宽高比来计算它的宽度或范围。
如图所示,Screen.width
和 Screen.height
是指游戏的 window 或显示器分辨率,如果您是 运行 游戏全屏。您还可以看到,与游戏相比,相机的纵横比可能不同 window。好消息是Unity提供了一个属性来获取相机的长宽比
float camVertExtent = cam.orthograpicSize;
float camHorzExtent = cam.aspect * camVertExtent;
现在我们有了相机的范围,让我们看一下您的地图及其边界框。
您尝试使用 bounds.size
计算,但如您所见,bounds.size.x
是边界框的宽度。仅当您的地图 bottom-left 在世界 space 中从 (0,0) 开始时,使用该大小才有效。更好的方法是使用 bounds.min
和 bounds.max
,它们已经 return 坐标在世界 space.
你的最终目标是相机应该在地图的范围内,即它的位置受到以下四个条件的限制:
(cam.transform.position.x - camHorzExtent) >= bounds.min.x // left
(cam.transform.position.x + camHorzExtent) <= bounds.max.x // right
(cam.transform.position.y - camVertExtent) >= bounds.min.y // bottom
(cam.transform.position.y + camVertExtent) <= bounds.max.y // top
现在你只需要获取玩家位置并将相机限制在这些条件下:
float leftBound = bounds.min.x + camHorzExtent;
float rightBound = bounds.max.x - camHorzExtent;
float bottomBound = bounds.min.y + camVertExtent;
float topBound = bounds.max.y - camVertExtent;
float camX = Mathf.Clamp(player.transform.position.x, leftBound, rightBound);
float camY = Mathf.Clamp(player.transform.position.y, bottomBound, topBound);
cam.transform.position = new Vector3(camX, camY, cam.transform.position.z);
如果所有摄像机的尺寸和纵横比都相同,您可以对所有玩家摄像机使用相同的边界,并且只为每个玩家计算 camX
和 camY
。
你应该使用这个简单但有用的东西unity 2d camera follow script
也可在 github 上使用。
https://gist.github.com/unity3diy/5aa0b098cb06b3ccbe47
using UnityEngine;
using System.Collections;
public class FollowCamera : MonoBehaviour {
public float interpVelocity;
public float minDistance;
public float followDistance;
public GameObject target;
public Vector3 offset;
Vector3 targetPos;
// Use this for initialization
void Start () {
targetPos = transform.position;
}
// Update is called once per frame
void FixedUpdate () {
if (target)
{
Vector3 posNoZ = transform.position;
posNoZ.z = target.transform.position.z;
Vector3 targetDirection = (target.transform.position - posNoZ);
interpVelocity = targetDirection.magnitude * 5f;
targetPos = transform.position + (targetDirection.normalized * interpVelocity * Time.deltaTime);
transform.position = Vector3.Lerp( transform.position, targetPos + offset, 0.25f);
}
}
}
大家好,有些人需要完整的代码才能将许多儿童精灵转换为空游戏对象,例如:
Background
--mountains1(sprite)
--mountains2(sprite)
--mountains3(sprite)
这段代码将循环到背景对象中,并绑定所有儿童精灵 :D,感谢@Stefan Hoffmann 的解释,我制作了一个 Frankestein 代码哈哈。我希望这对其他人有帮助,抱歉我的英语不好:(
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
private float rightBound;
private float leftBound;
private float topBound;
private float bottomBound;
private Vector3 pos;
private Transform target;
private Camera cam;
private Bounds bounds;
// Use this for initialization
void Start()
{
target = GameObject.FindWithTag("Player").transform;
foreach (SpriteRenderer spriteBounds in GameObject.Find("Background").GetComponentsInChildren<SpriteRenderer>())
{
bounds.Encapsulate(spriteBounds.bounds);
}
cam = this.gameObject.GetComponent<Camera>();
float camVertExtent = cam.orthographicSize;
float camHorzExtent = cam.aspect * camVertExtent;
Debug.Log(camVertExtent);
Debug.Log(camHorzExtent);
Debug.Log(cam.aspect);
Debug.Log(cam.orthographicSize);
leftBound = bounds.min.x + camHorzExtent;
rightBound = bounds.max.x - camHorzExtent;
bottomBound = bounds.min.y + camVertExtent;
topBound = bounds.max.y - camVertExtent;
Debug.Log("leftBound=" + leftBound);
Debug.Log("rightBound=" + rightBound);
Debug.Log("bottomBound=" + bottomBound);
Debug.Log("topBound=" + topBound);
}
// Update is called once per frame
void Update()
{
float camX = Mathf.Clamp(target.transform.position.x, leftBound, rightBound);
float camY = Mathf.Clamp(target.transform.position.y, bottomBound, topBound);
cam.transform.position = new Vector3(camX, camY, cam.transform.position.z);
}
}