在游戏中通常会实现的效果是玩家主角移动的时候,背景也可以跟着移动,要实现这种效果其实就是获取主角的位置,然后再改变摄像机的位置就可以了,这就需要通过脚本来实现。这个脚本添加到摄像机的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 = ; 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);
}
}

[Unity2D]实现背景的移动的更多相关文章

  1. Unity2D 背景图铺满与Camera.Size的计算公式

    在unity制作2D游戏的教程,背景图sprite铺满显示时Camaer的Size调到多少合适,作个笔记. 资源参数 background.png 2048x640,Sprite的像素单位:100 调 ...

  2. unity2D背景移动补偿从而获得3d错觉效果

    2d平台跳跃游戏当相机移动的时候背景跟随进行微调移动,从而使得玩家获得3d的错觉 using System.Collections;using System.Collections.Generic;u ...

  3. unity2D限制位置的背景移动补偿效果

    有时候我们想要背景可以跟随相机移动补偿,但是又不想该背景物体离原来的位置太远,比如我们想要一棵树在一个房子的后面,然后使用相机补偿使其跟随移动,达到3D错觉效果,但是我们又不想该物体偏离房屋太远.假设 ...

  4. Unity2D多分辨率屏幕适配方案(转载)

    一下内容转自:http://imgtec.eetrend.com/forum/3992 此文将阐述一种简单有效的Unity2D多分辨率屏幕适配方案,该方案适用于基于原生开发的Unity2D游戏,即没有 ...

  5. [Unity2D]游戏引擎介绍

    由于手机游戏的流行,目前2D游戏开发的需求量也越来越大了,因此Unity3D游戏引擎也增加了2D游戏开发的支持,之前是可以通过第三方的2D游戏组件可以支持2D游戏开发,现在是官方的版本就支持了.Uni ...

  6. [原创]一种Unity2D多分辨率屏幕适配方案

    此文将阐述一种简单有效的Unity2D多分辨率屏幕适配方案,该方案适用于基于原生开发的Unity2D游戏,即没有使用第三方2D插件,如Uni2D,2D toolkit等开发的游戏,NGUI插件不受这个 ...

  7. 一种Unity2D多分辨率屏幕适配方案

    http://www.cnblogs.com/flyFreeZn/p/4073655.html 此文将阐述一种简单有效的Unity2D多分辨率屏幕适配方案,该方案适用于基于原生开发的Unity2D游戏 ...

  8. CSS3 background-image背景图片相关介绍

    这里将会介绍如何通过background-image设置背景图片,以及背景图片的平铺.拉伸.偏移.设置大小等操作. 1. 背景图片样式分类 CSS中设置元素背景图片及其背景图片样式的属性主要以下几个: ...

  9. 冒泡,setinterval,背景图的div绑定事件,匿名函数问题

    1.会冒泡到兄弟元素么? $(function(){ $("#a").click(function(){alert("a")}) $("#b" ...

随机推荐

  1. poj 1318

    http://poj.org/problem?id=1318 这个题目还是比较水的,不过也可以提升你对字符串的熟悉度以及对一些排序函数和字符函数的使用. 大概的题意就是给你一个字典,这个字典有一些单词 ...

  2. javascript的事件监听与捕获和冒泡

    在前端开发中,我们经常需要对某些事件进行监听.这样只要在指定的元素上触发了该事件,就会执行一个回调来进行相关的操作. 而js中事件监听方法总共有三种,分别如下所示: element.addEventL ...

  3. python提取百万数据到csv文件

    转自:http://www.2cto.com/kf/201311/258112.html 今天有需求,需要把系统所有用户注册的id和邮箱等信息导出来提供给他们,在mysql里面count了下,大概有3 ...

  4. 在windows下用cygwin和eclipse搭建cocos2dx(2.1.4)的android开发环

    一.准备工作 需要下载和安装以下内容,请根据自己的操作系统选择x86和x64(我的是64位win7,我就拿64位说事) 1.jdk-7u25-windows-x64.exe(下载完后直接安装,一直下一 ...

  5. 跨域请求获取Solr json检索结果并高亮显示

    Solr提供了json格式的检索结果,然而在跨域的情况下如何调用呢?我们可以利用jquery提供的jsonp的方式获取Solr检索结果. <script type="text/java ...

  6. c++0x新特性实例(比较常用的)

    //array #include <array> void Foo() { array<> a; generate(a.begin(),a.end(),rand); sort( ...

  7. 解决虚拟机 正在决定eht0 的ip信息失败 无链接-- 虚拟机上linux redhat 上网问题

    对于虚拟机上,linux redhat上网的配置方式有三种 一.用setup命令进行配置(具体技巧可查setup命令的使用) 二.直接用 ifconfig eth0  ip地址进行配置 三.进入系统文 ...

  8. javascript的onbeforeunload函数在IOS上运行

    今天在做项目的时候,组长让我用iPad测试一下前面写的离线缓存,后退不刷新页面,发现在iPad上onbeforeunload函数在iPad上一带而过,不运行??? 无奈之下,发现原来在IOS上,有自己 ...

  9. Win7中打开chm文件内容无法显示问题

    今天下载了一个linux的2.6.22.14中文文档,下载后发现显示异常   www.2cto.com  怀疑是API的问题,连续从几个网站下来了很多版本,发现都存在这个问题,然后就开始自己的身上找原 ...

  10. OOP 7大原则

    1.  开闭原则(Open-Closed Principle,OCP) 1)定义:一个软件实体应当对扩展开放,对修改关闭( Software entities should be open for e ...