分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
在上一篇《
Unity 4.3 制作一个2D横版射击游戏》时,已经完成一个基本的射击游戏了。在这一篇将继续完善。
1.视差卷轴效果
为了达到这种视差卷轴的效果,可以让背景层以不同的速度进行移动,越远的层,移动地越慢。如果操作得当,这可以造成深度的错觉,这将很酷,又是可以容易做到的效果。在这里存在两个滚动:
- 主角随着摄像机向前推进
- 背景元素除了摄像机的移动外,又以不同的速度移动
一个循环的背景将在水平滚动的时候,一遍又一遍的重复进行显示。现在添加一个新的层到场景中,来显示背景元素。现有的层如下:
如下图所示:
接下来,先实现下不带背景循环的滚动。创建一个脚本,命名为" ScrollingScript",代码如下:
Layer | Loop | Position |
Background with the sky | Yes | (0, 0, 10) |
Background (1st row of flying platforms) | No | (0, 0, 9) |
Middleground (2nd row of flying platforms) | No | (0, 0, 5) |
Foreground with players and enemies | No | (0, 0, 0) |
接下来,先实现下不带背景循环的滚动。创建一个脚本,命名为" ScrollingScript",代码如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
using UnityEngine;
/// <summary> /// Parallax scrolling script that should be assigned to a layer /// </summary> public class ScrollingScript : MonoBehaviour { /// <summary> /// Scrolling speed /// </summary> public Vector2 speed = new Vector2( 2, 2); /// <summary> /// Moving direction /// </summary> public Vector2 direction = new Vector2(- 1, 0); /// <summary> /// Movement should be applied to camera /// </summary> public bool isLinkedToCamera = false; void Update() { // Movement Vector3 movement = new Vector3( speed.x * direction.x, speed.y * direction.y, 0); movement *= Time.deltaTime; transform.Translate(movement); // Move the camera if (isLinkedToCamera) { Camera.main.transform.Translate(movement); } } } |
将这个脚本附加到以下对象上,并且设置好其属性值,如下:
Layer | Speed | Direction | Linked to Camera |
0 - Background | (1, 1) | (-1, 0, 0) | No |
1 - Background elements | (1.5, 1.5) | (-1, 0, 0) | No |
2 - Middleground | (2.5, 2.5) | (-1, 0, 0) | No |
3 - Foreground | (1, 1) | (1, 0, 0) | Yes |
现在添加更多的元素到场景上:
- 添加两个天空背景到0 - Background
- 添加一些小的平台到1 - Background elements
- 添加一些平台到2 - Middleground
- 添加更多的敌人到3 - Foreground,放置在摄像机的右边
接下来,实现无限背景。当左侧的背景对象远离了摄像机的左边缘,那么就将它移到右侧去,一直这样无限循环,如下图所示:
要做到检查的对象渲染器是否在摄像机的可见范围内,需要一个类扩展。创建一个C#文件,命名为"
RendererExtensions.cs",代码如下:
1
2 3 4 5 6 7 8 9 10 |
using UnityEngine;
public static class RendererExtensions { public static bool IsVisibleFrom( this Renderer renderer, Camera camera) { Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera); return GeometryUtility.TestPlanesAABB(planes, renderer.bounds); } } |
修改"
ScrollingScript"脚本文件,为如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
using System.Collections.Generic;
using System.Linq; using UnityEngine; /// <summary> /// Parallax scrolling script that should be assigned to a layer /// </summary> public class ScrollingScript : MonoBehaviour { /// <summary> /// Scrolling speed /// </summary> public Vector2 speed = new Vector2( 10, 10); /// <summary> /// Moving direction /// </summary> public Vector2 direction = new Vector2(- 1, 0); /// <summary> /// Movement should be applied to camera /// </summary> public bool isLinkedToCamera = false; /// <summary> /// 1 - Background is infinite /// </summary> public bool isLooping = false; /// <summary> /// 2 - List of children with a renderer. /// </summary> private List<Transform> backgroundPart; // 3 - Get all the children void Start() { // For infinite background only if (isLooping) { // Get all the children of the layer with a renderer backgroundPart = new List<Transform>(); for ( int i = 0; i < transform.childCount; i++) { Transform child = transform.GetChild(i); // Add only the visible children if (child.renderer != null) { backgroundPart.Add(child); } } // Sort by position. // Note: Get the children from left to right. // We would need to add a few conditions to handle // all the possible scrolling directions. backgroundPart = backgroundPart.OrderBy( t => t.position.x ).ToList(); } } void Update() { // Movement Vector3 movement = new Vector3( speed.x * direction.x, speed.y * direction.y, 0); movement *= Time.deltaTime; transform.Translate(movement); // Move the camera if (isLinkedToCamera) { Camera.main.transform.Translate(movement); } // 4 - Loop if (isLooping) { // Get the first object. // The list is ordered from left (x position) to right. Transform firstChild = backgroundPart.FirstOrDefault(); if (firstChild != null) { // Check if the child is already (partly) before the camera. // We test the position first because the IsVisibleFrom // method is a bit heavier to execute. if (firstChild.position.x < Camera.main.transform.position.x) { // If the child is already on the left of the camera, // we test if it's completely outside and needs to be // recycled. if (firstChild.renderer.IsVisibleFrom(Camera.main) == false) { // Get the last child position. Transform lastChild = backgroundPart.LastOrDefault(); Vector3 lastPosition = lastChild.transform.position; Vector3 lastSize = (lastChild.renderer.bounds.max - lastChild.renderer.bounds.min); |