热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[Unity2D]实现背景的移动

在游戏中通常会实现的效果是玩家主角移动的时候,背景也可以跟着移动,要实现这种效果其实就是获取主角的位置,然后再改变摄像机的位置就可以了&#

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

 



推荐阅读
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 分享一款基于Java开发的经典贪吃蛇游戏实现
    本文介绍了一款使用Java语言开发的经典贪吃蛇游戏的实现。游戏主要由两个核心类组成:`GameFrame` 和 `GamePanel`。`GameFrame` 类负责设置游戏窗口的标题、关闭按钮以及是否允许调整窗口大小,并初始化数据模型以支持绘制操作。`GamePanel` 类则负责管理游戏中的蛇和苹果的逻辑与渲染,确保游戏的流畅运行和良好的用户体验。 ... [详细]
  • Objective-C 中的委托模式详解与应用 ... [详细]
  • 2.2 组件间父子通信机制详解
    2.2 组件间父子通信机制详解 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 属性类 `Properties` 是 `Hashtable` 类的子类,用于存储键值对形式的数据。该类在 Java 中广泛应用于配置文件的读取与写入,支持字符串类型的键和值。通过 `Properties` 类,开发者可以方便地进行配置信息的管理,确保应用程序的灵活性和可维护性。此外,`Properties` 类还提供了加载和保存属性文件的方法,使其在实际开发中具有较高的实用价值。 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 本文探讨了使用JavaScript在不同页面间传递参数的技术方法。具体而言,从a.html页面跳转至b.html时,如何携带参数并使b.html替代当前页面显示,而非新开窗口。文中详细介绍了实现这一功能的代码及注释,帮助开发者更好地理解和应用该技术。 ... [详细]
  • 本文将继续探讨 JavaScript 函数式编程的高级技巧及其实际应用。通过一个具体的寻路算法示例,我们将深入分析如何利用函数式编程的思想解决复杂问题。示例中,节点之间的连线代表路径,连线上的数字表示两点间的距离。我们将详细讲解如何通过递归和高阶函数等技术实现高效的寻路算法。 ... [详细]
  • 在多年使用Java 8进行新应用开发和现有应用迁移的过程中,我总结了一些非常实用的技术技巧。虽然我不赞同“最佳实践”这一术语,因为它可能暗示了通用的解决方案,但这些技巧在实际项目中确实能够显著提升开发效率和代码质量。本文将深入解析并探讨这四大高级技巧的具体应用,帮助开发者更好地利用Java 8的强大功能。 ... [详细]
  • 本文介绍了如何利用 Delphi 中的 IdTCPServer 和 IdTCPClient 控件实现高效的文件传输。这些控件在默认情况下采用阻塞模式,并且服务器端已经集成了多线程处理,能够支持任意大小的文件传输,无需担心数据包大小的限制。与传统的 ClientSocket 相比,Indy 控件提供了更为简洁和可靠的解决方案,特别适用于开发高性能的网络文件传输应用程序。 ... [详细]
  • 本文详细探讨了使用纯JavaScript开发经典贪吃蛇游戏的技术细节和实现方法。通过具体的代码示例,深入解析了游戏逻辑、动画效果及用户交互的实现过程,为开发者提供了宝贵的参考和实践经验。 ... [详细]
  • 本文深入解析了Java面向对象编程的核心概念及其应用,重点探讨了面向对象的三大特性:封装、继承和多态。封装确保了数据的安全性和代码的可维护性;继承支持代码的重用和扩展;多态则增强了程序的灵活性和可扩展性。通过具体示例,文章详细阐述了这些特性在实际开发中的应用和优势。 ... [详细]
author-avatar
北京超凡传媒
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有