1、需要的模型有玩家Player一名,一条跑道,若干障碍物
2、场景布置:
1)给跑道两侧加上空气墙
2)跑道靠近初始位置加个触发器当做此道路的抵达点(arrivePos)
3)给跑道某几个位置添加空物体,当做障碍物生成点 (bornPos)
3、然后就可以开始愉快的写代码了!
PS:具体关键知识点都在注释里,有时间再补充
1)首先需要玩家控制这一块的脚本,挂在玩家身上即可
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class moveController : MonoBehaviour {
// 摄像机位置
public Transform cameraTransform;
// 摄像机距离人物的距离
public float cameraDistance;
// 游戏管理器
public GameManager gameManager;
// 前进移动速度
float moveVSpeed;
// 水平移动速度
public float moveHSpeed = 5.0f;
// 跳跃高度
public float jumpHeight = 5.0f;
// 动画播放器
Animator m_animator;
// 起跳时间
double m_jumpBeginTime;
// 跳跃标志
int m_jumpState = 0;
// 最大速度
public float maxVSpeed = 8.0f;
// 最小速度
public float minVSpeed = 5.0f;
// Use this for initialization
void Start () {
//使player碰撞时角度不会改变
GetComponent<Rigidbody>().freezeRotation = true;
m_animator = GetComponent<Animator>();
if (m_animator == null)
print("null");
moveVSpeed = minVSpeed;
}
void Update () {
// 游戏结束
if (gameManager.isEnd)
{
return;
}
AnimatorStateInfo stateInfo = m_animator.GetCurrentAnimatorStateInfo(0);
if (stateInfo.fullPathHash == Animator.StringToHash("Base Layer.run"))
{
//若player在跑的话,跳跃状态即为false
m_jumpState = 0;
if (Input.GetButton("Jump"))
{
// 起跳,开始执行跳跃动作
m_animator.SetBool("Jump", true);
}
else
{
// 到地面
}
}
//若正在执行跳跃动画
else
{
// 掉下
m_jumpState = 1;
m_animator.SetBool("Jump", false);
}
//不按下时默认为0
float h = Input.GetAxis("Horizontal");
//this.transform.forward=(1,0,0)即向前,蓝色的轴
Vector3 vSpeed = new Vector3(this.transform.forward.x, this.transform.forward.y, this.transform.forward.z) * moveVSpeed ;
//this.transform.right=(0,0,-1) 向右,红色的轴
Vector3 hSpeed = new Vector3(this.transform.right.x, this.transform.right.y, this.transform.right.z) * moveHSpeed * h;
//this.transform.up=(0,1,0) 向上,绿色的轴
Vector3 jumpSpeed = new Vector3(this.transform.up.x, this.transform.up.y, this.transform.up.z) * jumpHeight * m_jumpState;
//此摄像机按X轴向前移动
Vector3 vCameraSpeed = new Vector3(this.transform.forward.x, this.transform.forward.y, this.transform.forward.z) * minVSpeed;
this.transform.position += (vSpeed + hSpeed + jumpSpeed) * Time.deltaTime;
cameraTransform.position += (vCameraSpeed) * Time.deltaTime;
//使player与摄像机的位置一直保持距离为:cameraDistance
// 当人物与摄像机距离小于cameraDistance时 让其加速
if (this.transform.position.x - cameraTransform.position.x < cameraDistance)
{
moveVSpeed += 0.1f;
if (moveVSpeed > maxVSpeed)
{
moveVSpeed = maxVSpeed;
}
}
// 超过时 让摄像机赶上
else if(this.transform.position.x - cameraTransform.position.x > cameraDistance)
{
moveVSpeed = minVSpeed;
cameraTransform.position = new Vector3(this.transform.position.x - cameraDistance, cameraTransform.position.y, cameraTransform.position.z);
}
// 摄像机超过人物
if(cameraTransform.position.x - this.transform.position.x > 0.0001f)
{
Debug.Log("你输啦!!!!!!!!!!");
gameManager.isEnd = true;
}
}
void OnTriggerEnter(Collider other)
{
// 每条道路抵达点碰撞检测
if (other.name.Equals("ArrivePos"))
{
//加载一条新的道路
gameManager.changeRoad(other.transform);
}
}
}
2)还需要一个游戏状态机
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GameManager : MonoBehaviour {
// 生成障碍物点列表
public List<Transform> bornPosList = new List<Transform>();
// 道路列表 三条道路的 transform
public List<Transform> roadList = new List<Transform>();
// 抵达点列表
public List<Transform> arrivePosList = new List<Transform>();
// 障碍物预置体列表
public List<GameObject> objPrefabList = new List<GameObject>();
// 目前的障碍物 字典类型,道路名称:此道路上的障碍物列表
Dictionary<string, List<GameObject>> objDict = new Dictionary<string, List<GameObject>>();
//道路距离
public int roadDistance;
//游戏状态
public bool isEnd = false;
// Use this for initialization
void Start () {
foreach(Transform road in roadList)
{
List<GameObject> objList = new List<GameObject>();
//每条道路的名字:一个空障碍物列表,赋值给objDict
objDict.Add(road.name, objList);
}
//初始状态先更新道路0和道路1
initRoad(0);
initRoad(1);
}
// Update is called once per frame
void Update () {
}
// 切出新的道路
public void changeRoad(Transform arrivePos)
{
//获取arrivePos的index,此时的index是上一条道路的
int index = arrivePosList.IndexOf(arrivePos);
//Debug.Log(index);
if (index >= 0)
{
//获取前一条道路的index
int lastIndex = (index + roadList.Count - 1)% roadList.Count;
//获取后一条道路的index
int nextIndex= (index + 1) % roadList.Count;
//则,我们需要把后一条道路的位置,变为前一条道路.位置+道路长度 完成道路更新 (因为就三条路,其实就是把后一条道路更新在最前面就行了)
roadList[lastIndex].position = roadList[nextIndex].position + new Vector3(roadDistance, 0, 0);
//再更新一下刚改变了位置的道路上的障碍物
initRoad(lastIndex);
}
else
{
Debug.LogError("arrivePos index is error");
return;
}
}
void initRoad(int index)
{
string roadName = roadList[index].name;
// 清空已有障碍物
foreach(GameObject obj in objDict[roadName])
{
Destroy(obj);
}
objDict[roadName].Clear();
// ******************添加障碍物***************//
//遍历索引为index的预制体指定生成位置
foreach(Transform pos in bornPosList[index])
{
//随机生成一个障碍物prefab Random.Range(min,max)
GameObject prefab = objPrefabList[Random.Range(0, objPrefabList.Count)];
//给prefab随机生成一个新角度
Vector3 eulerAngle = new Vector3(0, Random.Range(0, 360), 0);
GameObject obj = Instantiate(prefab, pos.position, Quaternion.Euler(eulerAngle)) as GameObject;
obj.tag = "Obstacle";
objDict[roadName].Add(obj);
}
}
}
3)同时,也需要在控制面板上把脚本里需要的引用拖过去
然后就完成啦~~~~