在游戏中通常会实现的效果是玩家主角移动的时候,背景也可以跟着移动,要实现这种效果其实就是获取主角的位置,然后再改变摄像机的位置就可以了,这就需要通过脚本来实现。这个脚本添加到摄像机的GameObject上,相当于摄像机的控制器。
using UnityEngine;using System.Collections;public class CameraController : MonoBehaviour{ public PlayerStateController.playerStates currentPlayerState = PlayerStateController.playerStates.idle; public GameObject playerObject = null;//玩家游戏对象 public float cameraTrackingSpeed = 0.2f; private Vector3 lastTargetPosition = Vector3.zero;//玩家最后的位置 private Vector3 currTargetPosition = Vector3.zero;//玩家当前的位置 private float currLerpDistance = 0.0f; void Start() { Vector3 playerPos = playerObject.transform.position;//玩家的位置 Vector3 cameraPos = transform.position;//相机的位置 Vector3 startTargPos = playerPos;//玩家初始化位置 startTargPos.z = cameraPos.z; lastTargetPosition = startTargPos; currTargetPosition = startTargPos; currLerpDistance = 1.0f; } void OnEnable() { PlayerStateController.onStateChange += onPlayerStateChange; } void OnDisable() { PlayerStateController.onStateChange -= onPlayerStateChange; } void onPlayerStateChange(PlayerStateController.playerStates newState) { currentPlayerState = newState; } void LateUpdate() { onStateCycle(); currLerpDistance += cameraTrackingSpeed; // 取两个向量之间的值 transform.position = Vector3.Lerp(lastTargetPosition, currTargetPosition, currLerpDistance); } void onStateCycle() { switch (currentPlayerState) { case PlayerStateController.playerStates.idle: trackPlayer(); break; case PlayerStateController.playerStates.left: trackPlayer(); break; case PlayerStateController.playerStates.right: trackPlayer(); break; case PlayerStateController.playerStates.jump: trackPlayer(); break; case PlayerStateController.playerStates.firingWeapon: trackPlayer(); break; } } void trackPlayer() { Vector3 currCamPos = transform.position;//当前相机位置 Vector3 currPlayerPos = playerObject.transform.position;//当前玩家位置 if (currCamPos.x == currPlayerPos.x && currCamPos.y == currPlayerPos.y)//位置一样,不移动 { currLerpDistance = 1.0f; lastTargetPosition = currCamPos; currTargetPosition = currCamPos; return; } currLerpDistance = 0.0f; lastTargetPosition = currCamPos;//最后的位置为相机的位置 currTargetPosition = currPlayerPos;//当前的位置为玩家的位置 currTargetPosition.z = currCamPos.z; } void stopTrackingPlayer() { Vector3 currCamPos = transform.position; currTargetPosition = currCamPos; lastTargetPosition = currCamPos; currLerpDistance = 1.0f; }}
如果要把背景的元素区分开来,不同的背景对象有不同的移动速度那么实现的方式会稍微复杂一点点。
1、首先得把背景的GameObject进行一下分类,如下所示:
2、给这个背景GameObject的分组添加一个脚本,也就是给_ParallaxLayers添加脚本,主要需要的参数就是摄像机对象、背景GameObject的分类数组、移动速度等。
脚本如下所示:
using UnityEngine;using System.Collections;public class ParallaxController : MonoBehaviour{ public GameObject[] clouds;//云层 public GameObject[] nearHills;//近山 public GameObject[] farHills;//远山 public GameObject[] lava;//地面 // 移动的速度 public float cloudLayerSpeedModifier; public float nearHillLayerSpeedModifier; public float farHillLayerSpeedModifier; public float lavalLayerSpeedModifier; public Camera myCamera; private Vector3 lastCamPos; void Start() { lastCamPos = myCamera.transform.position;//获取相机的位置 } void Update() { Vector3 currCamPos = myCamera.transform.position; float xPosDiff = lastCamPos.x - currCamPos.x;//计算相机x轴的变化 adjustParallaxPositionsForArray(clouds, cloudLayerSpeedModifier, xPosDiff); adjustParallaxPositionsForArray(nearHills, nearHillLayerSpeedModifier, xPosDiff); adjustParallaxPositionsForArray(farHills, farHillLayerSpeedModifier, xPosDiff); adjustParallaxPositionsForArray(lava, lavalLayerSpeedModifier, xPosDiff); lastCamPos = myCamera.transform.position; } // 数组来存储游戏对象 void adjustParallaxPositionsForArray(GameObject[] layerArray, float layerSpeedModifier, float xPosDiff) { // 遍历改变精灵的位置 for (int i = 0; i < layerArray.Length; i++) { Vector3 objPos = layerArray[i].transform.position; objPos.x += xPosDiff * layerSpeedModifier; layerArray[i].transform.position = objPos; } }}
另外一种实现的方案脚本:
using UnityEngine;using System.Collections;public class CameraFollow : MonoBehaviour { public float xMargin = 1f; // Distance in the x axis the player can move before the camera follows. public float yMargin = 1f; // Distance in the y axis the player can move before the camera follows. public float xSmooth = 8f; // How smoothly the camera catches up with it's target movement in the x axis. public float ySmooth = 8f; // How smoothly the camera catches up with it's target movement in the y axis. public Vector2 maxXAndY; // The maximum x and y coordinates the camera can have. public Vector2 minXAndY; // The minimum x and y coordinates the camera can have. private Transform player; // Reference to the player's transform. void Awake () { // Setting up the reference. // 查找玩家游戏对象 player = GameObject.FindGameObjectWithTag("Player").transform; } // 检查边缘 bool CheckXMargin() { // Returns true if the distance between the camera and the player in the x axis is greater than the x margin. // x轴变化的绝对值大于设定值 return Mathf.Abs(transform.position.x - player.position.x) > xMargin; } // 检查边缘 bool CheckYMargin() { // Returns true if the distance between the camera and the player in the y axis is greater than the y margin. // y轴变化的绝对值大于设定值 return Mathf.Abs(transform.position.y - player.position.y) > yMargin; } void FixedUpdate () { TrackPlayer(); } void TrackPlayer () { // By default the target x and y coordinates of the camera are it's current x and y coordinates. float targetX = transform.position.x; float targetY = transform.position.y; // If the player has moved beyond the x margin... if(CheckXMargin()) // ... the target x coordinate should be a Lerp between the camera's current x position and the player's current x position. // 在当前位置和最新位置之间插值 // Time.deltaTime 增量时间 以秒计算,完成最后一帧的时间(只读)。使用这个函数使和你的游戏帧速率无关 targetX = Mathf.Lerp(transform.position.x, player.position.x, xSmooth * Time.deltaTime); // If the player has moved beyond the y margin... if(CheckYMargin()) // ... the target y coordinate should be a Lerp between the camera's current y position and the player's current y position. targetY = Mathf.Lerp(transform.position.y, player.position.y, ySmooth * Time.deltaTime); // The target x and y coordinates should not be larger than the maximum or smaller than the minimum. // 把目标值限制在固定的范围 targetX = Mathf.Clamp(targetX, minXAndY.x, maxXAndY.x); targetY = Mathf.Clamp(targetY, minXAndY.y, maxXAndY.y); // Set the camera's position to the target position with the same z component. // 设置相机的位置 transform.position = new Vector3(targetX, targetY, transform.position.z); }}