题目:3d塔防游戏制作
一.准备阶段
1.学生:
唐凡 董晟
2.平台及使用材质包:
Unity3d ,Tower Defense Toolkit,c#
3
.分工:
唐凡: 编码及页面布局.
董晟: 材料包查找及使用解释,流程图绘制。
4.流程图绘制:
https://www.gliffy.com/
二. 具体过程
1.安装unity3d
首先是安装软件,我们是按照这个网站安装的,说的很详细。http://www.zf3d.com/Products_rj.asp?id=1068 倒是
安装的时候出现了缺失材料包的现象,后来去网上找了一堆材质包。倒是解决了这个问题。
2.一些基本的概念及要点
灯源(light):就像名字一样,这个是给予照明的,没有这个,摄像机就只能看见一片黑。
摄像机(camera):摄像机的拍摄的部分就是玩家视野内的部分。
运动脚本:采用的是c#制作的运动逻辑控制脚本。
3.目录设计与结构图
这个游戏的结构图如下:
4.操作步骤
(一)建立塔基安放点,即采用cube模块,把长宽设置为9,高设置为0.25。一共配置了八块。
cube配置
(二)光源和摄像机安放,大概设置在45角向下投射。
·
大概是
这个角度
(三)路径点脚本,采用的c#,采用的是
Tower Defense Toolkit
的模板,我进行了一点修改。使得路径点符合路径。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Path : MonoBehaviour {
public Transform[] waypoints;
public float heightOffsetOnPlatform=1;
public float dynamicWP=1;
public bool generatePathObject=true;
public bool showGizmo=true;
private Transform thisT;
//private GameObject thisObj;
private List<PathSection> path=new List<PathSection>();
void Awake(){
thisT=transform;
//thisObj=gameObject;
}
void Start(){
//run through the list, generate a list of PathSection
//if the element is a platform, generate the node and set it to walkable
for(int i=0; i<waypoints.Length; i++){
Transform wp=waypoints[i];
//check if this is a platform, BuildManager would have add the component and have them layered
if(wp.gameObject.layer==LayerManager.LayerPlatform()){
//Debug.Log("platform");
Platform platform=wp.gameObject.GetComponent<Platform>();
path.Add(new PathSection(platform));
}
else path.Add(new PathSection(wp.position));
}
//scan through the path, setup the platform pathSection if there's any
//first initiate all the basic parameter
for(int i=0; i<path.Count; i++){
PathSection pSec=path[i];
if(path[i].platform!=null){
//get previous and next pathSection
PathSection sec1=path[Mathf.Max(0, i-1)];
PathSection sec2=path[Mathf.Min(path.Count-1, i+1)];
//path[i].platform.SetNeighbouringWP(sec1, sec2);
pSec.platform.SetPathObject(this, pSec, sec1, sec2);
pSec.platform.SetWalkable(true);
if(!pSec.platform.IsNodeGenerated())
pSec.platform.GenerateNode(heightOffsetOnPlatform);
pSec.platform.SearchForNewPath(pSec);
}
}
//now the basic have been setup, setup the path
//~ for(int i=0; i<path.Count; i++){
//~ if(path[i].platform!=null){
//~ path.platform.GetPath();
//~ }
//~ }
if(generatePathObject){
CreateLinePath();
}
}
//create line-renderer along the path as indicator
void CreateLinePath(){
Vector3 offsetPos=new Vector3(0, 0, 0);
for(int i=1; i<waypoints.Length; i++){
//waypoint to waypoint
if(path[i].platform==null && path[i-1].platform==null){
GameObject obj=new GameObject();
obj.name="path"+i.ToString();
Transform objT=obj.transform;
objT.parent=thisT;
LineRenderer line=obj.AddComponent<LineRenderer>();
line.material=(Material)Resources.Load("PathMaterial");
line.SetWidth(0.3f, 0.3f);
line.SetPosition(0, waypoints[i-1].position+offsetPos);
line.SetPosition(1, waypoints[i].position+offsetPos);
}
//platform to waypoint
else if(path[i].platform==null && path[i-1].platform!=null){
GameObject obj=new GameObject();
obj.name="path"+i.ToString();
Transform objT=obj.transform;
objT.parent=thisT;
LineRenderer line=obj.AddComponent<LineRenderer>();
line.material=(Material)Resources.Load("PathMaterial");
line.SetWidth(0.3f, 0.3f);
List<Vector3> path1=path[i-1].GetSectionPath();
line.SetPosition(0, path1[path1.Count-1]+offsetPos);
line.SetPosition(1, waypoints[i].position+offsetPos);
}
//waypoint to platform
else if(path[i].platform!=null && path[i-1].platform==null){
GameObject obj=new GameObject();
obj.name="path"+i.ToString();
Transform objT=obj.transform;
objT.parent=thisT;
LineRenderer line=obj.AddComponent<LineRenderer>();
line.material=(Material)Resources.Load("PathMaterial");
line.SetWidth(0.3f, 0.3f);
List<Vector3> path1=path[i].GetSectionPath();
line.SetPosition(0, waypoints[i-1].position+offsetPos);
line.SetPosition(1, path1[0]+offsetPos);
}
//platform to platform
else if(path[i].platform!=null && path[i-1].platform!=null){
GameObject obj=new GameObject();
obj.name="path"+i.ToString();
Transform objT=obj.transform;
objT.parent=thisT;
LineRenderer line=obj.AddComponent<LineRenderer>();
line.material=(Material)Resources.Load("PathMaterial");
line.SetWidth(0.3f, 0.3f);
List<Vector3> path1=path[i-1].GetSectionPath();
List<Vector3> path2=path[i].GetSectionPath();
line.SetPosition(0, path1[path1.Count-1]+offsetPos);
line.SetPosition(1, path2[0]+offsetPos);
}
}
foreach(PathSection ps in path){
if(ps.platform==null)
Instantiate((GameObject)Resources.Load("wpNode"), ps.pos+offsetPos, Quaternion.identity);
}
}
public List<PathSection> GetPath(){
return path;
}
void OnDrawGizmos(){
if(showGizmo){
Gizmos.color = Color.blue;
if(waypoints!=null && waypoints.Length>0){
for(int i=1; i<waypoints.Length; i++){
Gizmos.DrawLine(waypoints[i-1].position, waypoints[i].position);
}
}
}
}
}
public class PathSection{
public Platform platform;
public Vector3 pos;
private List<Vector3> sectionPath=new List<Vector3>();
private int pathID=0; //a unique randomly generated number assigned whenever a new path is found
//so the unit on this platform can know that a new path has been updated
public PathSection(Vector3 p){
pos=p;
sectionPath.Add(pos);
}
public PathSection(Platform p){
platform=p;
}
public void SetSectionPath(List<Vector3> L, int id){
sectionPath=L;
pathID=id;
}
public List<Vector3> GetSectionPath(){
return sectionPath;
}
public int GetPathID(){
return pathID;
}
}
(三)UI设计
拖拽下方的按钮到上方的工作区,添加脚本。
按钮列表
工作区
(四)敌人生成器
敌人分为两种,一种是地面单位,一种是空中单位,需要写不同的脚本控制生产器的定时装置,以做到交替产生敌人。代码是自动生成的,只需要修改一下速度和血量设置。(另外说一句,血量的显示是生成的两个条,一个不断减小,另一个不变。)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class UnitCreep : Unit {
public float moveSpeed=3;
//修改这里的变量
public bool immuneToSlow=false;
public bool flying=false;
public float flightHeightOffset=3f;
public int[] value=new int[1];
public GameObject spawnEffect;
public GameObject deadEffect;
public GameObject scoreEffect;
public GameObject animationBody;
private Animation aniBody;
public AnimationClip[] animationSpawn;
public AnimationClip[] animationMove;
public AnimationClip[] animationHit;
public AnimationClip[] animationDead;
public AnimationClip[] animationScore;
public float moveAnimationModifier=1.0f;
public AudioClip audioSpawn;
public AudioClip audioHit;
public AudioClip audioDead;
public AudioClip audioScore;
[HideInInspector] public Vector3 dynamicOffset;
[HideInInspector] public int waveID;
public GameObject spawnUponDestroyed;
public int spawnNumber;
public override void Awake () {
base.Awake();
SetSubClassInt(this);
if(thisObj.collider==null){
SphereCollider col=thisObj.AddComponent<SphereCollider>();
col.center=new Vector3(0, 0.0f, 0);
col.radius=0.25f;
}
if(animationBody!=null){
aniBody=animationBody.GetComponent<Animation>();
if(aniBody==null) aniBody=animationBody.AddComponent<Animation>();
if(animationSpawn!=null && animationSpawn.Length>0){
foreach(AnimationClip clip in animationSpawn){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=1;
aniBody.animation[clip.name].wrapMode=WrapMode.Once;
}
}
if(animationMove!=null && animationMove.Length>0){
foreach(AnimationClip clip in animationMove){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=0;
aniBody.animation[clip.name].wrapMode=WrapMode.Loop;
}
}
if(animationHit!=null && animationHit.Length>0){
foreach(AnimationClip clip in animationHit){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=3;
aniBody.animation[clip.name].wrapMode=WrapMode.Once;
}
}
if(animationDead!=null && animationDead.Length>0){
foreach(AnimationClip clip in animationDead){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=3;
aniBody.animation[clip.name].wrapMode=WrapMode.Once;
}
}
if(animationScore!=null && animationScore.Length>0){
foreach(AnimationClip clip in animationScore){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=3;
aniBody.animation[clip.name].wrapMode=WrapMode.Once;
}
}
}
if(spawnEffect!=null) ObjectPoolManager.New(spawnEffect, 5, false);
if(deadEffect!=null) ObjectPoolManager.New(deadEffect, 5, false);
}
public override void Start () {
if(!flying) thisObj.layer=LayerManager.LayerCreep();
else thisObj.layer=LayerManager.LayerCreepF();
base.Start();
}
public void SetMoveSpeed(float moveSpd){
moveSpeed=moveSpd;
}
//init a unitCreep, give it a list of Vector3 point as the path it should follow
public void Init(List<Vector3> waypoints, int wID){
base.Init();
waveID=wID;
wp=waypoints;
wpMode=true;
if(flying) thisT.position+=new Vector3(0, flightHeightOffset, 0);
currentMoveSpd=moveSpeed;
if(aniBody!=null && animationMove!=null && animationMove.Length>0){
foreach(AnimationClip clip in animationMove){
aniBody.animation[clip.name].speed=currentMoveSpd*moveAnimationModifier;
}
}
float allowance=BuildManager.GetGridSize();
dynamicOffset=new Vector3(Random.Range(-allowance, allowance), 0, Random.Range(-allowance, allowance));
thisT.position+=dynamicOffset;
PlaySpawn();
PlayMove();
}
//init a unitCreep, give it a path instance so it can retirve the path
public void Init(Path p, int wID){
base.Init();
waveID=wID;
path=p;
wpMode=false;
if(flying) thisT.position+=new Vector3(0, flightHeightOffset, 0);
currentMoveSpd=moveSpeed;
if(aniBody!=null && animationMove!=null && animationMove.Length>0){
foreach(AnimationClip clip in animationMove){
aniBody.animation[clip.name].speed=currentMoveSpd*moveAnimationModifier;
}
}
//if using dynamic wap pos, set an offset based on gridsize
if(path.dynamicWP>0){
//float allowance=BuildManager.GetGridSize()*0.35f;
float allowance=path.dynamicWP;
dynamicOffset=new Vector3(Random.Range(-allowance, allowance), 0, Random.Range(-allowance, allowance));
thisT.position+=dynamicOffset;
}
else dynamicOffset=Vector3.zero;
if(spawnEffect!=null) ObjectPoolManager.Spawn(spawnEffect, thisT.position, Quaternion.identity);
PlaySpawn();
PlayMove();
}
public void Dead(){
GameControl.GainResource(value);
//for(int i=0; i<value.Length; i++){
// GameControl.GainResource(i, value[i]);
//}
if(deadEffect!=null) ObjectPoolManager.Spawn(deadEffect, thisT.position, Quaternion.identity);
float duration=PlayDead();
StartCoroutine(Unspawn(duration));
//spawn more unit if there's one assigned
if(spawnUponDestroyed!=null){
SpawnManager.AddActiveUnit(waveID, spawnNumber);
for(int i=0; i<spawnNumber; i++){
//generate a small offset position within the grid size so not all creep spawned on top of each other and not too far apart
float allowance=BuildManager.GetGridSize()/2;
float x=Random.Range(-allowance, allowance);
float y=Random.Range(-allowance, allowance);
Vector3 pos=thisT.position+new Vector3(x, 0, y);
GameObject obj=ObjectPoolManager.Spawn(spawnUponDestroyed, pos, thisT.rotation);
UnitCreep unit=obj.GetComponent<UnitCreep>();
unit.Init(path, waveID);
//resume the path currently followed by this unit
StartCoroutine(unit.ResumeParentPath(wpMode, wp, wpCounter, currentPS, subPath, currentPathID, subWPCounter));
}
}
}
public void Score(){
if(scoreEffect!=null) ObjectPoolManager.Spawn(scoreEffect, thisT.position, Quaternion.identity);
float duration=PlayScore();
StartCoroutine(Unspawn(duration));
}
public override void Update () {
base.Update();
//~ if(GetWPCounter()==wp.Count){
//~ //final waypoint reached
//~ WaypointReachEvent();
//~ ObjectPoolManager.Unspawn(thisObj);
//~ }
}
public void Stunned(){
if(aniBody!=null){
if(animationMove!=null && animationMove.Length>0){
for(int i=0; i<animationMove.Length; i++){
aniBody.Stop(animationMove[i].name);
}
}
}
}
public void Unstunned(){
PlayMove();
}
private AnimationClip[] animationAttack;
private AnimationClip animationIdle;
public void SetAttackAnimation(AnimationClip[] aniAttack){
animationAttack=aniAttack;
if(aniBody!=null && animationAttack!=null && animationAttack.Length>0){
foreach(AnimationClip clip in animationHit){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=5;
aniBody.animation[clip.name].wrapMode=WrapMode.Once;
}
}
}
public void SetIdleAnimation(AnimationClip aniIdle){
animationIdle=aniIdle;
if(aniBody!=null){
aniBody.AddClip(animationIdle, animationIdle.name);
aniBody.animation[animationIdle.name].layer=-1;
aniBody.animation[animationIdle.name].wrapMode=WrapMode.Loop;
}
}
public void StopAnimation(){
if(aniBody!=null) aniBody.Stop();
if(aniBody!=null && animationIdle!=null){
aniBody.Play(animationIdle.name);
}
}
public void ResumeAnimation(){
PlayMove();
}
public bool PlayAttack(){
if(aniBody!=null && animationAttack!=null && animationAttack.Length>0){
aniBody.CrossFade(animationAttack[Random.Range(0, animationAttack.Length-1)].name);
return true;
}
return false;
}
public void PlayMove(){
if(aniBody!=null && animationMove!=null && animationMove.Length>0){
aniBody.Play(animationMove[Random.Range(0, animationMove.Length-1)].name);
}
}
public void PlaySpawn(){
if(aniBody!=null && animationSpawn!=null && animationSpawn.Length>0){
aniBody.CrossFade(animationSpawn[Random.Range(0, animationSpawn.Length-1)].name);
}
if(audioSpawn!=null) AudioManager.PlaySound(audioSpawn, thisT.position);
}
public void PlayHit(){
//Debug.Log("Play hit");
if(aniBody!=null && animationHit!=null && animationHit.Length>0){
aniBody.CrossFade(animationHit[Random.Range(0, animationHit.Length-1)].name);
}
if(audioHit!=null) AudioManager.PlaySound(audioHit, thisT.position);
}
public float PlayDead(){
float duration=0;
if(aniBody!=null){
aniBody.Stop();
}
if(aniBody!=null && animationDead!=null && animationDead.Length>0){
int rand=Random.Range(0, animationDead.Length-1);
aniBody.CrossFade(animationDead[rand].name);
duration=animationDead[rand].length;
}
if(audioDead!=null){
AudioManager.PlaySound(audioDead, thisT.position);
duration=Mathf.Max(audioDead.length, duration);
}
return duration;
}
public float PlayScore(){
float duration=0;
if(aniBody!=null && animationScore!=null && animationScore.Length>0){
int rand=Random.Range(0, animationDead.Length-1);
aniBody.CrossFade(animationScore[rand].name);
duration=animationScore[rand].length;
}
if(audioScore!=null) {
AudioManager.PlaySound(audioScore, thisT.position);
duration=Mathf.Max(audioScore.length, duration);
}
return duration;
}
IEnumerator Unspawn(float duration){
yield return new WaitForSeconds(duration);
ObjectPoolManager.Unspawn(thisObj);
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class UnitCreep : Unit {
public float moveSpeed=3;
//修改这里的变量
public bool immuneToSlow=false;
public bool flying=false;
public float flightHeightOffset=3f;
public int[] value=new int[1];
public GameObject spawnEffect;
public GameObject deadEffect;
public GameObject scoreEffect;
public GameObject animationBody;
private Animation aniBody;
public AnimationClip[] animationSpawn;
public AnimationClip[] animationMove;
public AnimationClip[] animationHit;
public AnimationClip[] animationDead;
public AnimationClip[] animationScore;
public float moveAnimationModifier=1.0f;
public AudioClip audioSpawn;
public AudioClip audioHit;
public AudioClip audioDead;
public AudioClip audioScore;
[HideInInspector] public Vector3 dynamicOffset;
[HideInInspector] public int waveID;
public GameObject spawnUponDestroyed;
public int spawnNumber;
public override void Awake () {
base.Awake();
SetSubClassInt(this);
if(thisObj.collider==null){
SphereCollider col=thisObj.AddComponent<SphereCollider>();
col.center=new Vector3(0, 0.0f, 0);
col.radius=0.25f;
}
if(animationBody!=null){
aniBody=animationBody.GetComponent<Animation>();
if(aniBody==null) aniBody=animationBody.AddComponent<Animation>();
if(animationSpawn!=null && animationSpawn.Length>0){
foreach(AnimationClip clip in animationSpawn){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=1;
aniBody.animation[clip.name].wrapMode=WrapMode.Once;
}
}
if(animationMove!=null && animationMove.Length>0){
foreach(AnimationClip clip in animationMove){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=0;
aniBody.animation[clip.name].wrapMode=WrapMode.Loop;
}
}
if(animationHit!=null && animationHit.Length>0){
foreach(AnimationClip clip in animationHit){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=3;
aniBody.animation[clip.name].wrapMode=WrapMode.Once;
}
}
if(animationDead!=null && animationDead.Length>0){
foreach(AnimationClip clip in animationDead){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=3;
aniBody.animation[clip.name].wrapMode=WrapMode.Once;
}
}
if(animationScore!=null && animationScore.Length>0){
foreach(AnimationClip clip in animationScore){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=3;
aniBody.animation[clip.name].wrapMode=WrapMode.Once;
}
}
}
if(spawnEffect!=null) ObjectPoolManager.New(spawnEffect, 5, false);
if(deadEffect!=null) ObjectPoolManager.New(deadEffect, 5, false);
}
public override void Start () {
if(!flying) thisObj.layer=LayerManager.LayerCreep();
else thisObj.layer=LayerManager.LayerCreepF();
base.Start();
}
public void SetMoveSpeed(float moveSpd){
moveSpeed=moveSpd;
}
//init a unitCreep, give it a list of Vector3 point as the path it should follow
public void Init(List<Vector3> waypoints, int wID){
base.Init();
waveID=wID;
wp=waypoints;
wpMode=true;
if(flying) thisT.position+=new Vector3(0, flightHeightOffset, 0);
currentMoveSpd=moveSpeed;
if(aniBody!=null && animationMove!=null && animationMove.Length>0){
foreach(AnimationClip clip in animationMove){
aniBody.animation[clip.name].speed=currentMoveSpd*moveAnimationModifier;
}
}
float allowance=BuildManager.GetGridSize();
dynamicOffset=new Vector3(Random.Range(-allowance, allowance), 0, Random.Range(-allowance, allowance));
thisT.position+=dynamicOffset;
PlaySpawn();
PlayMove();
}
//init a unitCreep, give it a path instance so it can retirve the path
public void Init(Path p, int wID){
base.Init();
waveID=wID;
path=p;
wpMode=false;
if(flying) thisT.position+=new Vector3(0, flightHeightOffset, 0);
currentMoveSpd=moveSpeed;
if(aniBody!=null && animationMove!=null && animationMove.Length>0){
foreach(AnimationClip clip in animationMove){
aniBody.animation[clip.name].speed=currentMoveSpd*moveAnimationModifier;
}
}
//if using dynamic wap pos, set an offset based on gridsize
if(path.dynamicWP>0){
//float allowance=BuildManager.GetGridSize()*0.35f;
float allowance=path.dynamicWP;
dynamicOffset=new Vector3(Random.Range(-allowance, allowance), 0, Random.Range(-allowance, allowance));
thisT.position+=dynamicOffset;
}
else dynamicOffset=Vector3.zero;
if(spawnEffect!=null) ObjectPoolManager.Spawn(spawnEffect, thisT.position, Quaternion.identity);
PlaySpawn();
PlayMove();
}
public void Dead(){
GameControl.GainResource(value);
//for(int i=0; i<value.Length; i++){
// GameControl.GainResource(i, value[i]);
//}
if(deadEffect!=null) ObjectPoolManager.Spawn(deadEffect, thisT.position, Quaternion.identity);
float duration=PlayDead();
StartCoroutine(Unspawn(duration));
//spawn more unit if there's one assigned
if(spawnUponDestroyed!=null){
SpawnManager.AddActiveUnit(waveID, spawnNumber);
for(int i=0; i<spawnNumber; i++){
//generate a small offset position within the grid size so not all creep spawned on top of each other and not too far apart
float allowance=BuildManager.GetGridSize()/2;
float x=Random.Range(-allowance, allowance);
float y=Random.Range(-allowance, allowance);
Vector3 pos=thisT.position+new Vector3(x, 0, y);
GameObject obj=ObjectPoolManager.Spawn(spawnUponDestroyed, pos, thisT.rotation);
UnitCreep unit=obj.GetComponent<UnitCreep>();
unit.Init(path, waveID);
//resume the path currently followed by this unit
StartCoroutine(unit.ResumeParentPath(wpMode, wp, wpCounter, currentPS, subPath, currentPathID, subWPCounter));
}
}
}
public void Score(){
if(scoreEffect!=null) ObjectPoolManager.Spawn(scoreEffect, thisT.position, Quaternion.identity);
float duration=PlayScore();
StartCoroutine(Unspawn(duration));
}
public override void Update () {
base.Update();
//~ if(GetWPCounter()==wp.Count){
//~ //final waypoint reached
//~ WaypointReachEvent();
//~ ObjectPoolManager.Unspawn(thisObj);
//~ }
}
public void Stunned(){
if(aniBody!=null){
if(animationMove!=null && animationMove.Length>0){
for(int i=0; i<animationMove.Length; i++){
aniBody.Stop(animationMove[i].name);
}
}
}
}
public void Unstunned(){
PlayMove();
}
private AnimationClip[] animationAttack;
private AnimationClip animationIdle;
public void SetAttackAnimation(AnimationClip[] aniAttack){
animationAttack=aniAttack;
if(aniBody!=null && animationAttack!=null && animationAttack.Length>0){
foreach(AnimationClip clip in animationHit){
aniBody.AddClip(clip, clip.name);
aniBody.animation[clip.name].layer=5;
aniBody.animation[clip.name].wrapMode=WrapMode.Once;
}
}
}
public void SetIdleAnimation(AnimationClip aniIdle){
animationIdle=aniIdle;
if(aniBody!=null){
aniBody.AddClip(animationIdle, animationIdle.name);
aniBody.animation[animationIdle.name].layer=-1;
aniBody.animation[animationIdle.name].wrapMode=WrapMode.Loop;
}
}
public void StopAnimation(){
if(aniBody!=null) aniBody.Stop();
if(aniBody!=null && animationIdle!=null){
aniBody.Play(animationIdle.name);
}
}
public void ResumeAnimation(){
PlayMove();
}
public bool PlayAttack(){
if(aniBody!=null && animationAttack!=null && animationAttack.Length>0){
aniBody.CrossFade(animationAttack[Random.Range(0, animationAttack.Length-1)].name);
return true;
}
return false;
}
public void PlayMove(){
if(aniBody!=null && animationMove!=null && animationMove.Length>0){
aniBody.Play(animationMove[Random.Range(0, animationMove.Length-1)].name);
}
}
public void PlaySpawn(){
if(aniBody!=null && animationSpawn!=null && animationSpawn.Length>0){
aniBody.CrossFade(animationSpawn[Random.Range(0, animationSpawn.Length-1)].name);
}
if(audioSpawn!=null) AudioManager.PlaySound(audioSpawn, thisT.position);
}
public void PlayHit(){
//Debug.Log("Play hit");
if(aniBody!=null && animationHit!=null && animationHit.Length>0){
aniBody.CrossFade(animationHit[Random.Range(0, animationHit.Length-1)].name);
}
if(audioHit!=null) AudioManager.PlaySound(audioHit, thisT.position);
}
public float PlayDead(){
float duration=0;
if(aniBody!=null){
aniBody.Stop();
}
if(aniBody!=null && animationDead!=null && animationDead.Length>0){
int rand=Random.Range(0, animationDead.Length-1);
aniBody.CrossFade(animationDead[rand].name);
duration=animationDead[rand].length;
}
if(audioDead!=null){
AudioManager.PlaySound(audioDead, thisT.position);
duration=Mathf.Max(audioDead.length, duration);
}
return duration;
}
public float PlayScore(){
float duration=0;
if(aniBody!=null && animationScore!=null && animationScore.Length>0){
int rand=Random.Range(0, animationDead.Length-1);
aniBody.CrossFade(animationScore[rand].name);
duration=animationScore[rand].length;
}
if(audioScore!=null) {
AudioManager.PlaySound(audioScore, thisT.position);
duration=Mathf.Max(audioScore.length, duration);
}
return duration;
}
IEnumerator Unspawn(float duration){
yield return new WaitForSeconds(duration);
ObjectPoolManager.Unspawn(thisObj);
}
}
(五)运行图:
三.感想心得
我们在这一次的作业中,应老师的要求对已有软件做了3D游戏的制作。在这次作业完成过程中,我们不仅学习到了对软件开发的技术方面的知识,而且还学习到了一种不满足于已有软件的精神。对于我们学习计算机的人来说 ,本身对于软件的开发与维护就是我们以后工作的重点之一。而对于这种工作来说,一颗创新与不满足的心就是特别重要的。对已有软件性能上缺陷的改进,BUG的修复,以及对界面友好度的提升而这次的作业当中,我们也初步体会到了身为一个程序员维护的自己程序的辛苦。其中不仅要求在代码开发的还对代码做好备注,还要求我们不能对自己已开发的东西满足,要一直有进取精神,这样才能将自己做的代码做得更加出色