我正在制作一款游戏,最多可配备4个正交摄像机(最多4个玩家),根据玩家的数量占据不同数量的屏幕。
我有一个控制所有摄像机的脚本,设置相对于他们正在观看的玩家的位置。
我想要实现的是一种简单的头顶 - 跑步运动风格,相机将跟随玩家,但不会超出地图范围。
当相机是“方形”时,我已设法在左上角的相机中工作。 (如4人布局)。但是,其他相机根本没有正确跟踪,而在矩形双人模式下,顶部相机仍然左右移动太远。我很确定我确切地知道导致问题的代码行...但我不知道我需要做些什么来修复它...
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);
}
所以我非常确定我需要检查屏幕上相机的大小和相对位置,但我完全不知道自己需要做什么。
(编辑) 脚本说明:
启动时将摄像机定位在屏幕上的代码:
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;
}
}
编辑,所以无论形状如何,我都能得到第一台相机(所以在双人模式中,使用矩形相机,玩家-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??
答案 0 :(得分:10)
您的计算有几个问题。我想这只是运气,它适用于某些情况。虽然你的一般想法是正确的,但你正在使用错误的属性进行计算。基本上,您需要了解相机的纵横比,地图的边界框以及相机在边界处的行为方式。
我们需要相机的纵横比来计算其宽度或范围。
正如您在图片中看到的那样,Screen.width
和Screen.height
指的是游戏的窗口或显示器分辨率,以防您全屏运行游戏。您还可以看到,与游戏窗口相比,相机可能具有不同的宽高比。好消息是Unity提供了获取相机宽高比的属性。
float camVertExtent = cam.orthograpicSize;
float camHorzExtent = cam.aspect * camVertExtent;
现在我们有相机的范围,让我们来看看你的地图及其边界框。
您尝试使用bounds.size
进行计算,但正如您所看到的,bounds.size.x
是边界框的宽度。只有当地图的左下角从世界空间的(0,0)开始时,才能使用大小。更好的方法是使用已经返回世界空间坐标的bounds.min
和bounds.max
。
您的最终目标是相机应保持在地图的范围内,即其位置受以下四个条件的限制:
(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
。
答案 1 :(得分:2)
我想建议您解决问题的另一种方法。
您是否可以在地图的边框处添加高对撞机,以及相机的对撞机?然后你可以让相机跟随播放器(使用物理!),当玩家到达边界时,由于对撞机,相机不会过去。
然后,您可以轻松分割屏幕,了解您拥有多少玩家。 一个球员? - &GT;所有屏幕尺寸 两个球员? - &GT;相机1结束广告屏幕高度/ 2,相机2以屏幕高度/ 2 +1开始 等等
答案 2 :(得分:0)
大家好,有些人需要完整的代码才能将游戏对象与许多儿童精灵一起打入Empty Gameobject,如:
Background
--mountains1(sprite)
--mountains2(sprite)
--mountains3(sprite)
本守则将循环进入Background对象,并采取所有儿童精灵的界限:D,由于@Stefan Hoffmann的解释,我制作了一个Frankestein代码hahhaa。我希望这会对别人有所帮助,抱歉我的英语不好:(
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);
}
}
答案 3 :(得分:-1)
你应该使用这个简单但有用的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);
}
}
}