前言


说是基于unity的2D横版游戏,实际上只是一个初学unity与C#新人的练手Demo,目前还处于半成状态。美术资源方面全部出自unity免费资源,经过自己的小修,大致拼出了一个游戏。代码方面,仅仅初识C#语法,此前从未接触过面向对象编程的我,显然写出来的东西显然不堪入目,问题包括但不限于:1.未遵守命名规范。2.未领会面向对象编程的思想,代码复用随处可见。3.代码思路及其不清晰,动画状态转换判断一半靠动画机参数,一半靠代码里的if else(再三确认.jpg)。4.总体架构没想好,想到哪写哪,beAttackBox满足不了要求写个beAttackBoxOfEnemy,还不行就beAttackBoxOfBoss,看架势如果写完整个游戏,要写上千个脚本。5.维护性极差,脚本功能纵横交错,出了问题现在的我能解决,过一个月就只有上帝能解决了。
总而言之,这段小结仅出于记录自己黑历史的目的,冒着荣登知乎“你见过最烂的代码是怎样的”这一问题榜首的风险发布,不敢劳烦各位大佬斧正,只希望大伙就看个乐呵,尽量不要进行人身攻击,以下是展示部分。
分割线

游戏展示


由于还有有关游戏导出分辨率的问题尚未解决,展示仅在编译器中进行。

1.近战敌人演示

unity 2d游戏开发 unity2d游戏开发横屏格斗手游_unity3d


2.远程敌人演示

unity 2d游戏开发 unity2d游戏开发横屏格斗手游_unity3d_02


3.boss战(自己写的boss都能过不了?)

unity 2d游戏开发 unity2d游戏开发横屏格斗手游_游戏_03


部分代码展示


boss1AI

//bossAI形式不同于小怪enemyAI,不具有普适性。
//boss1行动模式用自然语言描述如下:
//在场景中,boss一直处于战斗状态,以若干秒为一个周期,根据所设计的概率随机选择一个符合条件(与玩家的距离、自身血量所决定的阶段、技能冷却情况)的
//行动(发动某攻击,接近玩家,远离玩家),在完成行动后,进入后摇时间,后摇结束后进入下一周期,在受击动画完成后若干秒,立刻进入下一个周期。
//行动并不仅限于一个动画,可以考虑两个动画进行组合以实现连招。boss子物体包含若干个范围盒,按由外到内的顺序排列,每进入一个范围盒,可随机选择的动作增加。
//由外到内,增加的可选择动作为:
//1.接近玩家。
//2.远离玩家、发动技能跳斩attack5(仅在该范围盒)、发动技能突刺attack2(二阶段新增技能旋转攻击attack4,隐身突袭attack3)。
//3.普通攻击attack1、击退踢腿attack6(后接突刺或跳斩)。
//具体数值见boss1Const

/*其余说明:1.boss面向改变不属于行动,于等待阶段进行。
 * 2.当血量低于50时,进入二阶段,立即进行三次隐身突袭attack3,并减少单个周期的时间以实现行动后摇减少,加速敌人攻击。
 * 3.一定时间内受击超过一定次数时,boss会踢腿击退接突刺或跳斩的连招
 * 
 * 
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class boss1AI : MonoBehaviour
{
	static public float HP;
	public enum BossState { range1, range2, range3 };//
	public BossState bossState = BossState.range1;
	public AnimationCurve jump;
	public AudioSource attack2;

	private Animator ani;
	private SpriteRenderer spr;
	private Rigidbody2D rid;
	private GameObject player;
	private bool isIdle;
	private float animationLength;
	private int[] moving=new int[10000];//用于记录boss行动的数组
	private int i = 0;
	private float waitingTime = 0;//后摇计时器
	private float movingTime = 0;//行动计时器
	private float attack3CD = 0;//特殊技能attack3计时器
	private int movingNumble = 0;//随机数,用于决定boss的下一步行动
	private int attack3Times = 3;//attack3技能单词释放次数
	private float jumpTime=0;
								 // Start is called before the first frame update
	void Start()
	{
		ani = gameObject.GetComponent<Animator>();
		spr = gameObject.GetComponent<SpriteRenderer>();
		rid = gameObject.GetComponent<Rigidbody2D>();
		player = GameObject.FindGameObjectWithTag("Player");
		//判断动画状态机播放的动画是否为Idle
		//引用组件
		HP = boss1Const.maxHP;
	}

	// Update is called once per frame
	private void FixedUpdate()
	{
		animationLength = ani.GetCurrentAnimatorStateInfo(0).length;//获取当前播放动画长度
		if (waitingTime >= boss1Const.waitingTime)
		{
			if (ani.GetBool("isIdle") == true)
			{
				roll:
				switch (bossState)
				{
					case BossState.range1:
						movingNumble = Random.Range(0, 15);//生成一个0到14之间的随机数(包含),数字大小决定了移动距离
						break;
					case BossState.range2:
						movingNumble = Random.Range(0, 60);//生成一个0到59之间的随机数(包含)15~34为跳斩,35-59为突刺,进入2阶段后,单数正常判定,双数为旋转攻击,隐身突袭为特殊技能,进入2阶段每5个循环释放一次
						break;
					case BossState.range3:
						movingNumble = Random.Range(35, 120);//生成一个0到119之间的随机数(包含)60~104为普攻,105~119为击退接突刺(或跳斩)
						break;					
				}
				//处于待机状态且不处于后摇时间中时,roll点决定boss下一步行动

				if (attack3CD <= 0 && (ani.GetInteger("attackingNumber") == 0 || ani.GetInteger("attackingNumber") == 3) && HP <= 0.5 * boss1Const.maxHP)
				{
					moving[++i] = 3;
				}
				else if (movingNumble >= 0 && movingNumble < 15)//接近玩家
				{
					moving[++i] = 0;
				}
				else if (movingNumble >= 15 && movingNumble < 35)
				{
					if (HP <= boss1Const.maxHP * 0.5 && movingNumble % 2 == 0)//旋转攻击(二阶段时)
					{
						moving[++i] = 4;
					}
					else//跳斩
					{
						moving[++i] = 5;
					}
				}
				else if (movingNumble >= 35 && movingNumble < 60)
				{
					if (HP <= boss1Const.maxHP * 0.5 && movingNumble % 2 == 0)//旋转攻击(二阶段时)
					{
						moving[++i] = 4;
					}
					else//突刺
					{
						moving[++i] = 2;
					}
				}
				else if (movingNumble >= 60 && movingNumble < 105)//普通攻击
				{
					moving[++i] = 1;
				}
				else if (movingNumble >= 105 && movingNumble <= 120)
				{
					moving[++i] = 6;	
				}
				//根据movingNumble确定下一步行动
				if(moving[i-1]==6)
				{
					if(i%2==0)
					{
						moving[i] = 2;
					}
					else
					{
						moving[i] = 5;
					}
				}
				//查看上一步行动,若为踢腿,则根据随机数指定下一步行动为突刺或跳斩

				if (i >= 2) 
				{
					if (moving[i] == moving[i - 1] && moving[i] == moving[i - 2] && moving[i] != 3) 
					{
						i--;
						goto roll;
					}
				}
				//查看即将进行的行动,若重复两次以上,重新roll点决定行动
			}
			if (HP <= 0.5 * boss1Const.maxHP) 
			{
				attack3CD -= Time.deltaTime;
			}
			//特殊技能冷却时间改变

			switch(moving[i])
			{
				case 0:
					doWalk(movingNumble);
					break;
				case 1:
					doAttack1();
					break;
				case 2:
					doAttack2();
					break;
				case 3:
					doAttack3();
					break;
				case 4:
					doAttack4();
					break;
				case 5:
					doAttack5();
					break;
				case 6:
					doAttack6();
					break;
			}
		}
		else if(HP>0)
		{
			doWait();
		}
		else
		{
			doDestroy();
		}
		//
	}
	void doWait()
	{
		waitingTime += Time.fixedDeltaTime;
		//累加后摇计时器

		doChangeFacing();
		//旋转面向	
	}
	void doWalk(float velocity)
	{
		ani.SetBool("isIdle", false);
		ani.SetBool("isWalking", true);
		movingTime += Time.fixedDeltaTime;
		if (movingTime > animationLength)
		{
			waitingTime = boss1Const.waitingTime-boss1Const.waitingTimeAfterWalk;
			movingTime = 0;
			ani.SetBool("isWalking", false);
			ani.SetBool("isIdle", true);
		}
		transform.Translate(Vector2.right * Time.fixedDeltaTime * (velocity / 60 + 0.25f) * boss1Const.walkSpeed, Space.Self);
		//接近玩家一段距离
	}
	void doAttack1()
	{
		ani.SetBool("isIdle", false);
		ani.SetInteger("attackingNumber", 1);
		movingTime += Time.fixedDeltaTime;
		if (spr.sprite.name == "attack-A5" || spr.sprite.name == "attack-A6" || spr.sprite.name == "attack-A7")
		{
			doMove(1.5f);
		}
		//根据动画播放进度进行相匹配的位移

		if (movingTime > animationLength)
		{
			waitingTime = boss1Const.waitingTime - boss1Const.waitingTimeAfterAttack1;
			movingTime = 0;
			ani.SetInteger("attackingNumber", 0);
			ani.SetBool("isIdle", true);
		}
	}
	//普攻

	void doAttack2()
	{
		ani.SetBool("isIdle", false);
		ani.SetInteger("attackingNumber", 2);
		movingTime += Time.fixedDeltaTime;
		if(spr.sprite.name=="attack-B4"&& attack2.isPlaying == false)
		{
			attack2.Play();	
		}
		if(spr.sprite.name=="attack-B3")
		{
			doChangeFacing();
		}
		if (spr.sprite.name == "attack-B4"||spr.sprite.name=="attack-B5" )
		{
			doMove(4f);
		}
		//根据动画播放进度进行相匹配的位移

		if (movingTime > animationLength)
		{
			waitingTime = boss1Const.waitingTime - boss1Const.waitingTimeAfterAttack2;
			movingTime = 0;
			ani.SetInteger("attackingNumber", 0);
			ani.SetBool("isIdle", true);
		}
	}
	//突刺

	void doAttack3()
	{
		ani.SetInteger("attackingNumber", 3);
		ani.SetBool("isIdle", false);
		ani.SetBool("isWalking", false);
		movingTime += Time.fixedDeltaTime;
		if (spr.sprite.name == "attack-C1")
		{
			spr.color = Color.Lerp(new Color(1, 1, 1, 1), new Color(1, 1, 1, 0), movingTime / animationLength * 3f);
		}
		else if(spr.sprite.name!="attack-C1"&&spr.sprite.name!="attack-C2")
		{
			spr.color = Color.Lerp(new Color(1, 1, 1, 0), new Color(1, 1, 1, 1), (movingTime - 0.5f * animationLength) * 3f);
		}
		//实现隐身效果

		if (spr.sprite.name=="attack-C2")
		{
			doFlash(player.transform.position - (Vector3.right + Random.Range(-1, 1) * Vector3.right*2) * 0.5f + Vector3.up * 0.5f);
			doChangeFacing();
			//随机瞬移至玩家身边并调整面向
		}
		if(spr.sprite.name=="attack-C7"||spr.sprite.name=="attack-C8")
		{
			doJump(boss1Const.jumpHeight*0.5f);
		}
		if (movingTime > animationLength)
		{
			if(attack3Times>1)
			{
				attack3Times--;
				movingTime = 0;
				waitingTime = boss1Const.waitingTime - boss1Const.waitingTimeAfterAttack3;
				ani.SetInteger("attackingNumber", 0);
				ani.SetBool("isIdle", true);
			}
			else
			{
				attack3Times = 3;
				movingTime = 0;
				waitingTime = boss1Const.waitingTime - boss1Const.waitingTimeAfterAttack3;
				attack3CD = boss1Const.attack3CD;
				ani.SetInteger("attackingNumber", 0);
				ani.SetBool("isIdle", true);
			}
		}
	}
	//隐身突袭

	void doAttack4()
	{
		ani.SetInteger("attackingNumber", 4);
		ani.SetBool("isIdle", false);
		movingTime += Time.fixedDeltaTime;
		if(spr.sprite.name!="attack-D1"&&spr.sprite.name!="attack-D2"&&spr.sprite.name!="attack-D12"&&spr.sprite.name!="attack-D7")
		{
			doMove(4f);
		}
		if(spr.sprite.name=="attack-D7")
		{
			doChangeFacing();
		}
		if (movingTime > animationLength)
		{
			waitingTime = boss1Const.waitingTime - boss1Const.waitingTimeAfterAttack4;
			movingTime = 0;
			ani.SetInteger("attackingNumber", 0);
			ani.SetBool("isIdle", true);
		}
	}
	//旋转攻击

	void doAttack5()
	{
		ani.SetInteger("attackingNumber", 5);
		ani.SetBool("isIdle", false);
		movingTime += Time.fixedDeltaTime;
		if(spr.sprite.name == "jump-attack-1" || spr.sprite.name== "jump-attack-2"||spr.sprite.name== "jump-attack-3")
		{
			doJump(boss1Const.jumpHeight);
		}
		if (spr.sprite.name != "jump-attack-8")
		{
			doMove(Random.Range(2.5f, 2.8f));
		}
		//根据动画播放进度进行相匹配的位移

		if (movingTime > animationLength)
		{
			waitingTime = boss1Const.waitingTime - boss1Const.waitingTimeAfterAttack5;
			movingTime = 0;
			ani.SetInteger("attackingNumber", 0);
			ani.SetBool("isIdle", true);
		}
	}
	//跳斩

	void doAttack6()
	{
		ani.SetInteger("attackingNumber", 6);
		ani.SetBool("isIdle", false);
		movingTime += Time.fixedDeltaTime;
		if (spr.sprite.name == "kick-3" || spr.sprite.name == "kick-4")
		{
			doMove(4f);
		}
		if (movingTime >= animationLength)
		{
			movingTime = 0;
			waitingTime = boss1Const.waitingTime - boss1Const.waitingTimeAfterAttack6;
			ani.SetInteger("attackingNumber", 0);
			ani.SetBool("isIdle", true);
		}
	}
	//踢腿

	void doMove(float velocity)
	{
		transform.Translate(Vector2.right * Time.fixedDeltaTime*velocity , Space.Self);
	}
	//位移

	void doChangeFacing()
	{
		if (player.transform.position.x <= transform.position.x)
		{
			transform.rotation = Quaternion.Euler(0, 180, 0);
		}
		else
		{
			transform.rotation = Quaternion.Euler(0, 0, 0);
		}
	}
	//改变面向

	void doJump(float jumpHeight)
	{
		jumpTime += Time.fixedDeltaTime;
		transform.Translate(new Vector3(0, jump.Evaluate(jumpTime) - jump.Evaluate(jumpTime - Time.fixedDeltaTime)) * jumpHeight, Space.World);
		if(jumpTime>=0.5f)
		{
			jumpTime = 0;
		}
	}
	//跳跃

	void doFlash(Vector3 Position)
	{
		transform.position = Position;
	}
	//闪烁

	void doDestroy()
	{
		ani.SetBool("isDead", true);
		movingTime += Time.deltaTime;
		if (movingTime >= animationLength)
		{
			StartCoroutine(reStart());
		}
	}
	IEnumerator reStart()
	{
		yield return new WaitForSecondsRealtime(3.0f);
		SceneManager.LoadScene("title");
	}
}

enemy1AI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class enemy1AI : MonoBehaviour
{

	private Animator ani;
	private SpriteRenderer spr;
	private Rigidbody2D rid;
	private GameObject attackBox;
	private GameObject beAttackBox;
	private GameObject isGroundBox;
	private BoxCollider2D attackBoxCollider;
	private GameObject player;
	private enemyState enemyState;
	private enemyConst enemyConst;
	//组件引用


	//状态
	private float attackTime = 0;
	private float wanderTime = 0;
	private float readyAttackTime = 0;
	private float velocity = 0;
	private float waitingTime= 0;
	private float hitTime = 0;
	//计时器

	// Start is called before the first frame update
	void Start()
    {
		ani = gameObject.GetComponent<Animator>();
		spr = gameObject.GetComponent<SpriteRenderer>();
		rid = gameObject.GetComponent<Rigidbody2D>();
		enemyConst = GetComponent<enemyConst>();
		player = GameObject.FindGameObjectWithTag("Player");
		//读取组件

		for (int i = 0; i < transform.childCount; i++)
		{
			switch (transform.GetChild(i).name)
			{
				case "attackBox":
					attackBox = transform.GetChild(i).gameObject;
					break;
				case "beAttackBox":
					beAttackBox = transform.GetChild(i).gameObject;
					break;
				case "isGroundBox":
					isGroundBox = transform.GetChild(i).gameObject;
					break;
			}
		}
		//读取子物体

		attackBoxCollider = attackBox.GetComponent<BoxCollider2D>();
		//读取子物体组件
		enemyState = GetComponent<enemyState>();
	}

	// Update is called once per frame
	private void FixedUpdate()
	{
		if(ani.GetBool("isDead")==false)
		{
			setGrativy();
			//根据敌人状态设置重力

			doWander();
			//警戒范围内无玩家时进行巡逻

			doChase();
			//玩家进入警戒范围后进行追击,并在脱离追击范围前持续追击

			doAttack();
			//玩家进入攻击范围内进行攻击

			doBeHit();
			//受击时播放受击动画
		}
		doDestroy();
		//死亡时播放死亡动画
	}
	void Update()
    {
		ani.SetFloat("attackSpeed", enemyConst.attackSpeed);
	}

	void doMove(float velocity,float speed)
	{
		if (velocity > 0)
		{
			transform.rotation = Quaternion.Euler(0, 0, 0);
		}
		else if (velocity < 0)
		{
			transform.rotation = Quaternion.Euler(0, 180, 0);
		}
		//判断是否需要旋转enemy1

		ani.SetFloat("velocity", velocity);
		transform.Translate(Vector2.right * Time.fixedDeltaTime * velocity * speed, Space.World);
		//左右移动enemy1
	}
	//移动enemy1

	void doWander()
	{
		if (enemyState.state == enemyState.State.wander && ani.GetBool("isBeingHit") == false) 
		{
			waitingTime = 0;
			float velocity = 0;
			wanderTime += Time.fixedDeltaTime;
			if (wanderTime <= 0.25 * enemyConst.wanderLength)
			{
				velocity = 1;
			}
			else if (wanderTime >= 0.25 * enemyConst.wanderLength && wanderTime <= enemyConst.wanderLength * 0.5)
			{
				velocity = 0;
			}
			else if (wanderTime >= 0.5 * enemyConst.wanderLength && wanderTime <= enemyConst.wanderLength * 0.75)
			{
				velocity = -1;
			}
			else if (wanderTime >= 0.75 * enemyConst.wanderLength && wanderTime <= enemyConst.wanderLength)
			{
				velocity = 0;
			}
			else
			{
				wanderTime = 0;
			}

			//根据计时器设定velocity方向以实现巡逻,单次巡逻时长为enemy1Const.wanderLength,巡逻模式为右走-停止-左走-停止

			doMove(velocity,enemyConst.walkSpeed);
			//移动enemy1
		}
	}
	void doChase()
	{
		if (enemyState.state == enemyState.State.chase && ani.GetBool("isAttacking1") == false && ani.GetBool("isAttacking2") == false && ani.GetBool("isBeingHit") == false) 
		{
			ani.SetFloat("velocity", 0);
			waitingTime += Time.fixedDeltaTime;
			if (waitingTime >= enemyConst.baseChangeTime) 
			{
				if (transform.position.x - player.transform.position.x >= 0)
				{
					velocity = -1;
				}
				else if (player.transform.position.x - transform.position.x >= 0)
				{
					velocity = 1;
				}
				doMove(velocity, enemyConst.chaseSpeed);
			}
		}
	}
	void doAttack()
	{
		readyAttackTime += Time.fixedDeltaTime;
		if (enemyState.state == enemyState.State.attack || ani.GetBool("isAttacking1") == true || ani.GetBool("isAttacking2") == true)   //确保攻击动画播放完毕
		{
			if (ani.GetBool("isGrounded") == true && ani.GetBool("isBeingHit") == false && ani.GetBool("isAttacking1") == false && ani.GetBool("isAttacking2") == false && enemyState.state == enemyState.State.attack && readyAttackTime >= enemyConst.baseAttackTime)  
			{
				attackTime = 0;
				ani.SetFloat("velocity", 0);//站定进行攻击
				if (Random.Range(1,3)==1)
				{
					ani.SetBool("isAttacking1", true);
				}
				else
				{
					ani.SetBool("isAttacking2", true);
				}
			}
			//随机发起一种形式的新攻击

			if (ani.GetBool("isAttacking1") == true)
			{
				attackTime += Time.fixedDeltaTime;
				if (attackTime >= 1 / enemyConst.attackSpeed * enemyConst.attackAnimation1Length)
				{
					ani.SetBool("isAttacking1", false);
					waitingTime = 0;
					readyAttackTime = 0;
				}
			}
			else if(ani.GetBool("isAttacking2")==true)
			{
				attackTime += Time.fixedDeltaTime;
				if (attackTime >= 1 / enemyConst.attackSpeed * enemyConst.attackAnimation2Length) 
				{
					ani.SetBool("isAttacking2", false);
					waitingTime = 0;
					readyAttackTime = 0;
				}
			}
			//攻击计时,以转化动画状态
		}
	}
	void doBeHit()
	{
		if (ani.GetBool("isBeingHit") == true)
		{
			hitTime += Time.fixedDeltaTime;
			if (hitTime >= enemyConst.hitAnimationLength)
			{
				hitTime = 0;
				ani.SetBool("isBeingHit", false);
			}
		}
	}
	void doDestroy()
	{
		if(enemyState.HP<=0)
		{
			ani.SetBool("isDead", true);
			Destroy(gameObject, enemyConst.deadAnimationLength);
		}
	}
	private void setGrativy()
	{
		if (ani.GetBool("isBeingHit") == true)
		{
			rid.gravityScale = 0;
		}
		else
		{
			rid.gravityScale = 10;
		}
		//受击状态下重力设置为0以实现受击时的僵直;
	}
}

enemy2AI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class enemy2AI : MonoBehaviour
{
	public GameObject arrow;
	private Animator ani;
	private SpriteRenderer spr;
	private Rigidbody2D rid;
	private GameObject attackBox;
	private GameObject beAttackBox;
	private GameObject isGroundBox;
	private BoxCollider2D attackBoxCollider;
	private GameObject player;
	private enemyState enemyState;
	private enemyConst enemyConst;
	private GameObject shootPoint;
	private GameObject shootPoint2;
	//组件引用


	//状态
	private float attackTime = 0;
	private float wanderTime = 0;
	private float readyAttackTime = 0;
	private float velocity = 0;
	private float waitingTime = 0;
	private float hitTime = 0;
	private bool havingInstantiateArrow = false;
	//计时器
	 
	// Start is called before the first frame update
	void Start()
	{
		ani = gameObject.GetComponent<Animator>();
		spr = gameObject.GetComponent<SpriteRenderer>();
		rid = gameObject.GetComponent<Rigidbody2D>();
		enemyConst = GetComponent<enemyConst>();
		player = GameObject.FindGameObjectWithTag("Player");
		//读取组件

		for (int i = 0; i < transform.childCount; i++)
		{
			switch (transform.GetChild(i).name)
			{
				case "attackBox":
					attackBox = transform.GetChild(i).gameObject;
					break;
				case "beAttackBox":
					beAttackBox = transform.GetChild(i).gameObject;
					break;
				case "isGroundBox":
					isGroundBox = transform.GetChild(i).gameObject;
					break;
				case "shootPoint":
					shootPoint = transform.GetChild(i).gameObject;
					break;
				case "shootPoint2":
					shootPoint2 = transform.GetChild(i).gameObject;
					break;
			}
		}
		//读取子物体

		attackBoxCollider = attackBox.GetComponent<BoxCollider2D>();
		//读取子物体组件
		enemyState = GetComponent<enemyState>();
	}

	// Update is called once per frame
	private void FixedUpdate()
	{
		if (ani.GetBool("isDead") == false)
		{
			setGrativy();
			//根据敌人状态设置重力

			doWander();
			//警戒范围内无玩家时进行巡逻

			doChase();
			//玩家进入警戒范围后进行追击,并在脱离追击范围前持续追击

			doAttack();
			//玩家进入攻击范围内进行攻击

			doBeHit();
			//受击时播放受击动画
		}
		doDestroy();
		//死亡时播放死亡动画
	}
	void Update()
	{
		ani.SetFloat("attackSpeed", enemyConst.attackSpeed);
	}

	void doMove(float velocity, float speed)
	{
		if (velocity > 0)
		{
			transform.rotation = Quaternion.Euler(0, 0, 0);
		}
		else if (velocity < 0)
		{
			transform.rotation = Quaternion.Euler(0, 180, 0);
		}
		//判断是否需要旋转enemy1

		ani.SetFloat("velocity", velocity);
		transform.Translate(Vector2.right * Time.fixedDeltaTime * velocity * speed, Space.World);
		//左右移动enemy1
	}
	//移动enemy1

	void doWander()
	{
		if (enemyState.state == enemyState.State.wander && ani.GetBool("isBeingHit") == false)
		{
			waitingTime = 0;
			float velocity = 0;
			wanderTime += Time.fixedDeltaTime;
			if (wanderTime <= 0.25 * enemyConst.wanderLength)
			{
				velocity = 1;
			}
			else if (wanderTime >= 0.25 * enemyConst.wanderLength && wanderTime <= enemyConst.wanderLength * 0.5)
			{
				velocity = 0;
			}
			else if (wanderTime >= 0.5 * enemyConst.wanderLength && wanderTime <= enemyConst.wanderLength * 0.75)
			{
				velocity = -1;
			}
			else if (wanderTime >= 0.75 * enemyConst.wanderLength && wanderTime <= enemyConst.wanderLength)
			{
				velocity = 0;
			}
			else
			{
				wanderTime = 0;
			}

			//根据计时器设定velocity方向以实现巡逻,单次巡逻时长为enemy1Const.wanderLength,巡逻模式为右走-停止-左走-停止

			doMove(velocity, enemyConst.walkSpeed);
			//移动enemy1
		}
	}
	void doChase()
	{
		if (enemyState.state == enemyState.State.chase && ani.GetBool("isAttacking1") == false && ani.GetBool("isAttacking2") == false && ani.GetBool("isBeingHit") == false)
		{
			ani.SetFloat("velocity", 0);
			waitingTime += Time.fixedDeltaTime;
			if (waitingTime >= enemyConst.baseChangeTime)
			{
				if (transform.position.x - player.transform.position.x >= 0)
				{
					velocity = -1;
				}
				else if (player.transform.position.x - transform.position.x >= 0)
				{
					velocity = 1;
				}
				doMove(velocity, enemyConst.chaseSpeed);
			}
		}
	}
	void doAttack()
	{
		readyAttackTime += Time.fixedDeltaTime;
		if (enemyState.state == enemyState.State.attack || ani.GetBool("isAttacking1") == true || ani.GetBool("isAttacking2") == true)   //确保攻击动画播放完毕
		{
			if (ani.GetBool("isGrounded") == true && ani.GetBool("isBeingHit") == false && ani.GetBool("isAttacking1") == false && ani.GetBool("isAttacking2") == false && enemyState.state == enemyState.State.attack && readyAttackTime >= enemyConst.baseAttackTime)
			{
				attackTime = 0;
				ani.SetFloat("velocity", 0);//站定进行攻击
				if (player.transform.position.y + 1 >= transform.position.y)  //判断是否需要向下射箭
				{
					ani.SetBool("isAttacking1", true);				
				}
				else
				{
					ani.SetBool("isAttacking2", true);
				}
			}
			//根据玩家位置发动攻击

			if (ani.GetBool("isAttacking1") == true)
			{
				attackTime += Time.fixedDeltaTime;
				if (spr.sprite.name == "attack-A4"&&havingInstantiateArrow==false)
				{
					havingInstantiateArrow = true;
					Instantiate(arrow, shootPoint.transform.position, transform.rotation);
				}
				//生成水平的箭

				if (attackTime >= 1 / enemyConst.attackSpeed * enemyConst.attackAnimation1Length)
				{				
					ani.SetBool("isAttacking1", false);
					havingInstantiateArrow = false;
					waitingTime = 0;
					readyAttackTime = 0;
				}
				//结束动画
			}
			else if (ani.GetBool("isAttacking2") == true)
			{
				attackTime += Time.fixedDeltaTime;
				if (spr.sprite.name == "attack-B4" && havingInstantiateArrow == false)
				{
					havingInstantiateArrow = true;
					Instantiate(arrow, shootPoint2.transform.position, Quaternion.Euler(0, transform.rotation.y*180, 315));
				}
				//生成斜向下的箭

				if (attackTime >= 1 / enemyConst.attackSpeed * enemyConst.attackAnimation2Length)
				{
					ani.SetBool("isAttacking2", false);
					havingInstantiateArrow = false;
					waitingTime = 0;
					readyAttackTime = 0;
				}
				//结束动画
			}
			//攻击计时,以转化动画状态

		}
	}
	void doBeHit()
	{
		if (ani.GetBool("isBeingHit") == true)
		{
			hitTime += Time.fixedDeltaTime;
			if (hitTime >= enemyConst.hitAnimationLength)
			{
				hitTime = 0;
				ani.SetBool("isBeingHit", false);
			}
		}
	}
	void doDestroy()
	{
		if (enemyState.HP <= 0)
		{
			ani.SetBool("isDead", true);
			Destroy(gameObject, enemyConst.deadAnimationLength);
		}
	}
	private void setGrativy()
	{
		if (ani.GetBool("isBeingHit") == true)
		{
			rid.gravityScale = 0;
		}
		else
		{
			rid.gravityScale = 10;
		}
		//受击状态下重力设置为0以实现受击时的僵直;
	}
}


总结


历经二十天的努力,我的第一款游戏demo的制作算是告一段落了,尽管还有数不清的不足之处,但是起码是一个可以运行的游戏了。我不敢说自己已经尽全力去把它做到最好了,不过我想下一次,我会做的更好。