unity商店demo学习:跑酷游戏

本文素材和代码全部来自unity asset store里面的3D Infinite Runner Toolkit项目

步骤

场景一:TitleScene

1 搭建开始界面场景

这个场景是开启游戏的第一个界面,用于选择切换到正式游戏场景或者商店。

只需要拖入主场景模型和一个角色模型即可,并添加UI资源。

2 添加角色动画逻辑和场景切换逻辑脚本

将要切换的脚本设置为一个变量名,然后切换场景的脚本就可以在不同button间复用

<span style="white-space:pre">	</span>void OnMouseUpAsButton(){
		this.guiTexture.texture = normal;
		Application.LoadLevel (levelName);
	}

场景二:Shop

1 搭建商店界面场景

商店场景用于角色选择和购买,当然还可以扩展其他功能,比如购买道具什么的。

也是导入相关模型就行了,添加UI资源。

2 界面交互基本逻辑脚本

触摸(光标滑动)

<span style="white-space:pre">	</span>IEnumerator SelectDirection(){
		bool input = false;
		while (input == false) {
			if((Input.mousePosition.x - getMousePos.x) < -40){
				indexSelect++;
				if(indexSelect >= players.Length-1){
					indexSelect = players.Length-1;
				}
				input = true;
			}

			if((Input.mousePosition.x - getMousePos.x) > 40){
				indexSelect--;
				if(indexSelect <= 0){
					indexSelect = 0;
				}
				input = true;
			}

			if(Input.GetMouseButtonUp(0)){
				input = true;
			}
			yield return 0;
		}

角色移位

<span style="white-space:pre">	</span>IEnumerator MoveToPoint(){
		while (Vector3.Distance(transform.position, point[indexSelect]) > 0.01f) {
			transform.position = Vector3.Lerp(transform.position, point[indexSelect], 10 * Time.deltaTime);
			yield return 0;
		}

		transform.position = point [indexSelect];

		StartCoroutine (WaitInput ());
	}

场景三:PlayGame

1 搭建游戏初始场景

载入街道等初始模型到场景,调整漫反射光

2 添加游戏角色

给角色添加刚体、碰撞体、控制脚本和动画控制器,然后存为预设体。

角色控制有跳、滑,左移右移还有二段跳,分别重写了键盘控制和触摸控制的接口。

<span style="white-space:pre">	</span>IEnumerator MoveBack(){
		float z = transform.position.z-0.5f;
		bool complete = false;
		while(complete == false){
			transform.position = Vector3.Lerp(transform.position, new Vector3(transform.position.x,transform.position.y,z),2*Time.deltaTime);
			if((transform.position.z - z) < 0.05f){
				complete = true;
			}
			yield return 0;
		}

		yield return 0;
	}

	private void MoveForward(){
		speedMove = GameAttribute.gameAttribute.speed;

		if(characterController.isGrounded){
			moveDir = Vector3.zero;
			if(directInput == DirectionInput.Up){
				Jump();
				if(isDoubleJump){
					jumpSecond = true;
				}
			}
		}else{
			if(directInput == DirectionInput.Down){
				QuickGround();
			}
			if(directInput == DirectionInput.Up){
				if(jumpSecond){
					JumpSeccond();
					jumpSecond = false;
				}
			}

			if(animationManager.animationState != animationManager.Jump
				&& animationManager.animationState != animationManager.JumpSecond
				&& animationManager.animationState != animationManager.Roll){
				animationManager.animationState = animationManager.JumpLoop;
			}
		}
		moveDir.z = 0;
		moveDir += this.transform.TransformDirection(Vector3.forward*speedMove);
		moveDir.y -= gravity * Time.deltaTime;

		CheckSideCollision ();
		characterController.Move((moveDir+direction)*Time.deltaTime);
	}

与障碍物碰撞逻辑。

<span style="white-space:pre">	</span>private void CheckSideCollision(){
			if (positionStand == Position.Right) {
				if((int)characterController.collisionFlags == 5 || characterController.collisionFlags == CollisionFlags.Sides){
					if(transform.position.x < 1.75f && checkSideCollision == false){
						Debug.Log("Hit");
						CameraFollow.instace.ActiveShake();
						positionStand = Position.Middle;
						checkSideCollision = true;
					}
				}
			}

			if (positionStand == Position.Left) {
				if((int)characterController.collisionFlags == 5 || characterController.collisionFlags == CollisionFlags.Sides){
					if(transform.position.x > -1.75f && checkSideCollision == false){
						Debug.Log("Hit");
						CameraFollow.instace.ActiveShake();
						positionStand = Position.Middle;
						checkSideCollision = true;
					}
				}
			}

			if(positionStand == Position.Middle){
				if((int)characterController.collisionFlags == 5 || characterController.collisionFlags == CollisionFlags.Sides){
					if(transform.position.x < -0.05f && checkSideCollision == false){
						Debug.Log("Hit");
						CameraFollow.instace.ActiveShake();
						positionStand = Position.Left;

						checkSideCollision = true;
					}else if(transform.position.x > 0.05f && checkSideCollision == false){
						Debug.Log("Hit");
						CameraFollow.instace.ActiveShake();
						positionStand = Position.Right;
						checkSideCollision = true;
					}
				}
			}

		if (checkSideCollision == true) {
			countDeleyInput += Time.deltaTime;
			if(countDeleyInput >= 1f){
				checkSideCollision = false;
				countDeleyInput = 0;
			}
		}
	}

金币拾取

<span style="white-space:pre">	</span>public void Magnet(float time){
		StopCoroutine("CancleMagnet");
		magnet.SetActive(true);
		timeMagnet = time;
		StartCoroutine(CancleMagnet());
	}

3 创建游戏控制器

添加空物体到场景,挂载脚本,异步加载场景、开始游戏、动态创建游戏物体,得分更新以及重置。

<span style="white-space:pre">	</span>//Loading method
	IEnumerator WaitLoading(){
		while(patSysm.loadingComplete == false){
			yield return 0;
		}
		StartCoroutine(InitPlayer());
	}

	//Spawn player method
	IEnumerator InitPlayer(){
		GameObject go = (GameObject)Instantiate(playerPref[selectPlayer], posStart, Quaternion.identity);
		cameraFol.target = go.transform;
		yield return 0;
		StartCoroutine(UpdatePerDistance());
	}

	//update distance score
	IEnumerator UpdatePerDistance(){
		while(true){
			if(PatternSystem.instance.loadingComplete){
				if(GameAttribute.gameAttribute.pause == false
					&& GameAttribute.gameAttribute.isPlaying == true
					&& GameAttribute.gameAttribute.life > 0){
					if(Controller.instace.transform.position.z > 0){
						GameAttribute.gameAttribute.distance += GameAttribute.gameAttribute.speed * Time.deltaTime;
						distanceCheck += GameAttribute.gameAttribute.speed * Time.deltaTime;
						if(distanceCheck >= speedAddEveryDistance){
							GameAttribute.gameAttribute.speed += speedAdd;
							if(GameAttribute.gameAttribute.speed >= speedMax){
								GameAttribute.gameAttribute.speed = speedMax;
							}
							countAddSpeed++;
							distanceCheck = 0;
						}
					}
				}
			}
			yield return 0;
		}
	}

	//reset game
	public IEnumerator ResetGame(){
		GameAttribute.gameAttribute.isPlaying = false;
		GUIManager.instance.showSumGUI = true;
		int oldCoind = GameData.LoadCoin ();
		GameData.SaveCoin((int)GameAttribute.gameAttribute.coin+oldCoind);
		distanceCheck = 0;
		countAddSpeed = 0;
		yield return 0;
	}

4 设置摄像机跟随

主摄像机挂载脚本,主要有跟随、重置和晃动逻辑

<span style="white-space:pre">	</span>void LateUpdate(){
		if(target != null){
			if(target.position.z >= 0){
				if(shake == false){
					posCamera.x = Mathf.Lerp(posCamera.x, target.position.x, 5 * Time.deltaTime);
					posCamera.y = Mathf.Lerp(posCamera.y, target.position.y + height, 5 * Time.deltaTime);
					posCamera.z = Mathf.Lerp(posCamera.z, target.position.z + distance, GameAttribute.gameAttribute.speed); //* Time.deltaTime);
					transform.position = posCamera;
					angleCam.x = angle;
					angleCam.y = Mathf.Lerp(angleCam.y, 0, 1 * Time.deltaTime);
					angleCam.z = transform.eulerAngles.z;
					transform.eulerAngles = Vector3.Lerp(transform.eulerAngles, angleCam, 1 * Time.deltaTime);
				}
			}else{
				if(PatternSystem.instance.loadingComplete == true){
					Vector3 dummy = Vector3.zero;
					posCamera.x = Mathf.Lerp(posCamera.x, 0, 5 * Time.deltaTime);
					posCamera.y = Mathf.Lerp(posCamera.y, dummy.y + height, 5 * Time.deltaTime);
					posCamera.z = dummy.z + distance;
					transform.position = posCamera;
					angleCam.x = angle;
					angleCam.y = transform.eulerAngles.y;
					angleCam.z = transform.eulerAngles.z;
					transform.eulerAngles = angleCam;
				}
			}
		}
	}

	//Reset camera when charater die
	public void Reset(){
		shake = false;
		Vector3 dummy = Vector3.zero;
		posCamera.x = 0;
		posCamera.y = dummy.y + height;
		posCamera.z = dummy.z + distance;
		transform.position = posCamera;
		angleCam.x = angle;
		angleCam.y = transform.eulerAngles.y;
		angleCam.z = transform.eulerAngles.z;
		transform.eulerAngles = angleCam;
	}

	//Shake camera
	public void ActiveShake(){
		shake = true;
		StartCoroutine(ShakeCamera());
	}

5 调整场景物体的尺寸

可以用标准立方体作为标尺来衡量场景物体的长宽高,使得游戏角色和场景物体比例得当。

6 添加游戏物体实例管理系统

创建空物体,挂载脚本,用于动态管理场景物体的更新(比如街道的无限延长,障碍物的随机产生等等)

<span style="white-space:pre">	</span>IEnumerator AddBuilding(){
		QueueFloor qFloor = queneFloor[0];
		queneFloor.RemoveRange(0,1);
		int i = 0;
		randomPattern = Random.Range(0, patternBuilding.Count);
		randomItem = Random.Range(0, patternItem.Count);
		while(i < building_Script.Count){
			int j = 0;
			while(j < patternBuilding[randomPattern].stateBuilding_Left.Length){
				CheckAddBuilding_Left(i,j,qFloor);
				j++;
			}
			j = 0;
			while(j < patternBuilding[randomPattern].stateBuilding_Right.Length){
				CheckAddBuilding_Right(i,j,qFloor);
				j++;
			}
			i++;
		}
		yield return 0;
		i = 0;
		CheckTypeItemFormAdd(qFloor, i);
		yield return 0;
		qFloor.floorObj.transform.position = posFloorLast;
		posFloorLast.z += nextPosFloor;
		queneFloor.Add(qFloor);
		StartCoroutine(WaitCheckFloor());
		yield return 0;
	}
<span style="white-space:pre">	</span>void AddItemWihtType_SubRight(QueueFloor floor, int slotIndex,int type){
		if(patternItem[randomItem].itemType_SubRight[slotIndex].x == type){
			int j = 0;
			while(j < amount_Item_Pattern_SubRight[type-1]){
				if(j < item_Type_Script[type-1].itemList.Count){
					if(item_Type_Script[type-1].itemList[j].itemActive == false
					   && floor.floorItemSlotClass.floor_Slot_SubRight[slotIndex] == false){
						SetPosItem_SubRight_For_Type(slotIndex,type-1,j,floor, patternItem[randomItem].itemType_SubRight[slotIndex].y);
						j = 0;
					}
				}
				j++;
			}
		}
	}

7 设置障碍物摆放

这里用到unity一个非常棒的工具,可以用图形化的手段对内部数据结构进行配置,实现所见即所得

如图,可以手动配置街道物体,接到障碍物,很好的关卡设置编辑器。

编译

将项目编译为可执行文件,需要在build设置里面添加所有scene,注意顺序。

游戏效果

开始界面

商店

游戏中

时间: 2024-08-11 11:06:05

unity商店demo学习:跑酷游戏的相关文章

unity商店demo学习:俯视视角RPG游戏

一下所有素材和源码都来自unity商店的实例 Top-Down RPG Starter Kit ,这个demo是unity商店上最好的入门级rpg游戏实例,麻雀虽小,五脏俱全,想要弄清楚一个标准的rpg游戏的方方面面,这个是很好的选择. ps:demo写得很高深,看得不是很懂,准备慢慢研究. 来一张工程全貌图. 这是一个俯视视角(可以调整视角)的卡通风格3D角色扮演游戏,配着动听又欢快的背景音乐,还有那萌萌哒的怪物,仿佛又回到了初中时玩冒险岛online的时候~~,额,不废话,主要模块如下: 游

【Unity 3D】学习笔记三十五:游戏实例——摄像机切换镜头

摄像机切换镜头 在游戏中常常会切换摄像机来观察某一个游戏对象,能够说.在3D游戏开发中,摄像头的切换是不可或缺的. 这次我们学习总结下摄像机怎么切换镜头. 代码: private var Camera0: GameObject; private var Camera1: GameObject; private var Camera2: GameObject; private var Camera: GameObject; function Start() { //获取摄像机对象 Camera =

【Unity 3D】学习笔记三十四:游戏元素——常用编辑器组件

常用编辑器组件 unity的特色之一就是编辑器可视化,很多常用的功能都可以在编辑器中完成.常用的编辑器可分为两种:原有组件和拓展组件.原有组件是编辑器原生的一些功能,拓展组件是编辑器智商通过脚本拓展的新功能. 摄像机 摄像机是unity最为核心组件之一,游戏界面中显示的一切内容都得需要摄像机来照射才能显示.摄像机组件的参数如下: clear flags:背景显示内容,默认的是skybox.前提是必须在render settings 中设置天空盒子材质. background:背景显示颜色,如果没

【Unity 3D】学习笔记二十六:unity游戏脚本(六)

在3D游戏世界中,任何一个游戏对象在创建的时候都会附带Transform(变换)组件,并且该组件是无法删除的,也不应该删除.在unity中,Transform面板一共有3个属性: Position  (位置) Rotation(旋转) Scale(缩放) 这三个值都是用来调整游戏对象在游戏界面中的位置,状态等相关参数. Position  (位置) 任何一个游戏对象的三维坐标都保存在Vector3容器中,该容器记录对象在X轴,Y轴,Z轴的坐标.一旦Vector33容器中的坐标发生变化,那么Sce

【Unity 3D】学习笔记三十三:游戏元素——天空盒子

天空盒子 一般的3D游戏都会有着北京百年一遇的蓝天,让人惊叹不已.其实天空这个效果没有什么神秘的只需用到天空盒子这个组件就行,可以将天空设想成一个巨大的盒子,这个盒子将整个游戏视图和所有的游戏元素包含其中.在unity中制作天空盒子非常方便,只需要像设置其他组件一样设置下就行了.在制作天空盒子之前,我们需要搜集一些天空的贴图,不过,unity很方便的为开发者提供了天空盒子的资源包.首先在project视图中点击鼠标右键,然后选择import package--skyboxes即可添加天空盒子的资

【Unity 3D】学习笔记三十二:游戏元素——游戏光源

游戏光源 在3D游戏中,光源是一个非常具有特色的游戏组件.用来提升游戏画面质感的.如果没有加入光源,游戏场景可能就会显得很昏暗.在unity中提供了三种不同的光源类型:点光源,聚光灯,平行光. 点光源 顾名思义,点光源是从一个点向周围散发出光的光源,就像电灯一样.创建点光源在hierarchy视图中点击create--point light: 创建完以后,点击点光源对象,在右侧inspector视图中可以看到点光源的所有信息: type:光源的类型.有point(点光源),directional

【Unity 3D】学习笔记二十九:游戏实例——简单小地图制作

任何的学习,光看不练是学不好的.所以这次就总结回顾下怎么制作MMROPG类游戏中的小地图.在MMROPG类游戏里,主角在游戏世界里走动时,一般在屏幕右上角都会有一个区域来显示当前游戏场景的小地图.主角在游戏世界里走动,小地图里代表着主角的小标记也会随之移动.那怎么实现咧? 首先需要确定两个贴图,第一个是右上角的小地图背景贴图,应该是从Y轴俯视向下截取主角所在的位置大地图.第二个就是主角的位置大贴图.在本例中,因为没有学习unity地图制作,所以地图用一个面对象代替,主角用立方体代替,使用GUI来

unity + win8.1 apps 小游戏demo

unity3d用的人挺多...本来想写个3d游戏试试..额..貌似挺麻烦.. .....先用unity写个简单的2d游戏吧.. (adsw回车  或者  触摸屏虚拟摇杆) 开发环境 unity4.5.1f3      vs2013 express       win8.1 实现方法如下 1.创建自己的坦克Sprite 2.创建敌方坦克Prefab 3.创建子弹Prefab 4.添加虚拟摇杆 5.碰撞检测 具体实现 1.控制自己坦克的代码 if (Input.GetKey (KeyCode.W))

【Unity 3D】学习笔记二十七:unity游戏脚本(七)

使用C#编写游戏脚本 在前面提到,unity支持三种语言编写脚本:js,C#,boo.入门的时候建议只用js,因为js比较简单易懂,语法也不是很严格.但后来晋级的时候推荐使用C#,因为它比较符合unity的编程思想,执行效率更高.下面总结下怎么使用C#编写脚本. 继承MonoBehaviour类 在unity中,任何一个脚本,包括上述三种语言都需要去继承MonoBehaviour这个类.为什么我们之前写JS代码的时候没有继承咧?因为在创建JS代码的时候,系统会将其类名与继承关系隐藏起来. 在pr