如何为在播放模式下实例化并在 Unity 3d 中使用相机位置重新创建的对象添加视差
Posted
技术标签:
【中文标题】如何为在播放模式下实例化并在 Unity 3d 中使用相机位置重新创建的对象添加视差【英文标题】:How to add parallax to objects instantiated in play mode and recreated with camera position in Unity 3d 【发布时间】:2019-03-24 18:55:04 【问题描述】:所以我无尽的 2d 游戏在背景中有 2 层山脉,我想在上面添加视差,近层需要比演员/相机慢,而远层要最慢。问题是,我不能直接向它们添加动作脚本,因为它们是根据随机主题颜色在播放模式下随机实例化的,所以它们是从下面的脚本中一个接一个地创建的,但我想添加一个动作在 x 轴上比相机速度慢,同时让它在最后一个结束时连续重新创建。
这是创建新山脉的脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PathManager : MonoBehaviour
public static PathManager Instance;
public GameObject CoinFragments;
public GameObject SlideArrow;
public float parallaxSpeed = 5f; //
private GameObject lastPathObject;
private float PathXPosition;
private GameObject lastMountainFar;
private float MountainFarXPosition;
private GameObject lastMountainNear;
private float MountainNearXPosition;
private float StarXPostion;
private float lastCameraX; //
// Use this for initialization
void Start ()
Instance = this;
// Update is called once per frame
void Update()
private void LateUpdate()
// Check for new Near Mountain
if (lastMountainNear != null && GamePlayCameraManager.Instance.MainCamera.transform.position.x > lastMountainNear.transform.position.x)
this.GenerateNearMountain();
// Check for new Far Mountain
if (lastMountainFar != null && GamePlayCameraManager.Instance.MainCamera.transform.position.x > lastMountainFar.transform.position.x)
this.GenerateFarMountain();
// Start Creating Mountains
public void StartMountainCreation()
MountainNearXPosition = GamePlayCameraManager.Instance.MainCamera.transform.position.x;
MountainFarXPosition = GamePlayCameraManager.Instance.MainCamera.transform.position.x;
this.GenerateNearMountain();
this.GenerateFarMountain();
private void GenerateNearMountain()
Vector3 MountainPosition = new Vector3(MountainNearXPosition - 4f, -3.6f, 10f);
lastMountainNear = Instantiate(ThemeManager.Instance.SelectedMountainNear, MountainPosition, Quaternion.identity);
MountainNearXPosition = MountainNearXPosition + lastMountainNear.GetComponent<Renderer>().bounds.size.x - 0.01f;
//float deltaX = GamePlayCameraManager.Instance.MainCamera.transform.position.x - lastCameraX;
//lastCameraX = GamePlayCameraManager.Instance.MainCamera.transform.position.x;
//lastMountainNear.transform.position += Vector3.right * (deltaX * parallaxSpeed);
private void GenerateFarMountain()
Vector3 MountainPosition = new Vector3(MountainFarXPosition - 4f, -3.6f, 22f);
lastMountainFar = Instantiate(ThemeManager.Instance.SelectedMountainFar, MountainPosition, Quaternion.identity);
MountainFarXPosition = MountainFarXPosition + lastMountainFar.GetComponent<Renderer>().bounds.size.x - 0.01f;
这是我的相机移动脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GamePlayCameraManager : MonoBehaviour
public static GamePlayCameraManager Instance; // Singleton Instance
public Camera MainCamera; // Main Camera
private Vector3 offset;
// Use this for initialization
void Start ()
Instance = this;
MainCamera.transform.position = new Vector3(0, 0, -10);
// Update is called once per frame
void Update ()
void LateUpdate()
if (GameStateManager.GameState == GameState.Set || GameStateManager.GameState == GameState.Playing)
MainCamera.transform.position = new Vector3(this.offset.x + ActorManager.Instance.Actor.transform.position.x + 0.8f, 0, -10);
// Fixed Update Method
void FixedUpdate()
public void FindCameraOffset()
this.offset = ActorManager.Instance.Actor.transform.position - MainCamera.transform.position + new Vector3(1.5f, 0f, 0f);
【问题讨论】:
【参考方案1】:首先,您应该查看pooling 您的山对象,这样您就不会无休止地浪费cpu 和内存来创建它们。
一旦您将它们汇集到您的PathManager
中,您首先需要知道相机在最后一帧中移动了多远,然后告诉山据此移动。您必须在相机管理器中引用您的 PathManager
。
在您的相机经理的LateUpdate
:
if (GameStateManager.GameState == GameState.Set || GameStateManager.GameState == GameState.Playing)
Vector3 newPosition = new Vector3(this.offset.x + ActorManager.Instance.Actor.transform.position.x + 0.8f, 0, -10);
float cameraMoveAmount = newPosition.x - MainCamera.transform.position.x;
MainCamera.transform.position = newPosition;
pathManager.MoveMountains(cameraMoveAmount)
然后,在您的 PathManager 中,使用 moveAmount 更改所有山脉的位置,以及创建下一个山脉的位置。在此之后,您应该检查是否需要显示新的山脉,而不是在 PathManager 的LateUpdate
中。这是因为您需要在检查添加新山之前移动山,如果您在不同的LateUpdate
电话中使用它们,则无法保证首先发生。
类似这样的:
// How fast the mountain layers are going to move in the direction of the camera.
// 0.0f - will not move with the camera, mountains will slide out of frame at normal speed.
// 1.0f - will move with the camera, no movement will be visible in frame.
public float nearMountainMoveSpeed = 0.5;
public float farMountainMoveSpeed = 0.9f;
. . .
public void MoveMountains(float cameraMoveAmount)
float nearMountainParallaxMove = nearMountainMoveSpeed * cameraMoveAmount;
float farMountainParallaxMove = farMountainMoveSpeed * cameraMoveAmount;
// Move the near mountains & their next placement
MountainNearXPosition += nearMountainParallaxMove;
foreach (GameObject nearMountain in pooledNearMountains)
nearMountain.transform.position = nearMountain.transform.position + new Vector3(nearMountainParallaxMove,0f,0f);
// Check for new Near Mountain
if (lastMountainNear != null && GamePlayCameraManager.Instance.MainCamera.transform.position.x > lastMountainNear.transform.position.x)
this.GenerateNearMountain();
// Move the far mountains & their next placement
MountainFarXPosition += farMountainParallaxMove;
foreach (GameObject farMountain in pooledFarMountains)
farMountain.transform.position = farMountain.transform.position + new Vector3(farMountainParallaxMove,0f,0f);
// Check for new Far Mountain
if (lastMountainFar != null && GamePlayCameraManager.Instance.MainCamera.transform.position.x > lastMountainFar.transform.position.x)
this.GenerateFarMountain();
顺便说一句,如果您最终更改了代码并拥有一个游戏对象,其中所有 farMountains 作为子对象,一个将所有 nearMountains 作为子对象,那么您可以只移动这些父游戏对象的变换,而不是循环穿过每一座山。当然,您需要移动它的数量是相同的。
【讨论】:
非常感谢您的详细回答,但相机管理器的最后一行给出了错误“访问非静态成员 `PathManager.MoveMountains(float)”需要对象引用” 它是小写的pathManager
,因为它是对您的PathManager
实例的引用。您必须将其添加到您的GamePlayCameraManager
以上是关于如何为在播放模式下实例化并在 Unity 3d 中使用相机位置重新创建的对象添加视差的主要内容,如果未能解决你的问题,请参考以下文章