一.游戏背景
生化实验的实验室中,不可预料的灾难即将降临,所有研究的实验体全部变异逃出,为拯救世界必须进入实验室拿到研究试剂然后逃出。
二.游戏展示
1.主页面(主要表现主角进入实验室的场景)
2.主页面跳转
3.爬楼梯
4.拾取道具
5.攻击怪物
7.滑行
8.触发开关
9.攻击实验体
三、核心代码实现
1.主角动画实现(状态机)
用Anitor.SetFloat("状态机属性名", 需要给的值));来控制主角动画控制,通过代码和状态机条件调整属性值来控制各个动画(为了省事就只做了一个这样的状态机,其实也可以更换角色状态机的动画控制器来切换————嘻嘻)。
if(!isJump&&Horizontal<0) //左移
{
Anitor.SetFloat("Flog", Input.GetAxis("Horizontal"));
transform.position += new Vector3(Horizontal*moveSpeed * Time.deltaTime, 0, 0);
}
if(isJump&&Horizontal<0)
{
transform.position += new Vector3(Horizontal*moveSpeed * Time.deltaTime, 0, 0);
}
if (!isJump && Horizontal >0) //右移
{
Anitor.SetFloat("Flog", Input.GetAxis("Horizontal"));
transform.position += new Vector3(Horizontal *moveSpeed* Time.deltaTime, 0, 0);
}
if (isJump && Horizontal >0)
{
transform.position += new Vector3(Horizontal *moveSpeed* Time.deltaTime, 0, 0);
}
//跳跃
if(Input.GetKeyDown(KeyCode.Space)&&!isJump && isclimb != true)
{
Anitor.SetFloat("Flog", 0);
isJump = true;
Rigbd.velocity=new Vector2 (0,Jump); //施加一个向上的力
TittleY = transform.localScale.y;
}
//开火
if(Input.GetKeyDown(KeyCode.U)&&bulletNumber!=0)
{
Debug.Log(bulletNumber + "u");
Anitor.SetBool("Attack", true);
Anitor.SetBool("DirectionRight", DirectionRight);
GameManeger.instance.BulletNumber--;
if (DirectionRight)
{
Debug.Log("111");
GameObject Newbullet= Instantiate(BulletPrefabs,transform.position,Quaternion.identity);
bulletRigbd = Newbullet.GetComponent<Rigidbody2D>();
bulletRigbd.AddForce(Vector3.right * Force);
}
else
{
GameObject Newbullet = Instantiate(BulletPrefabs, transform.position, Quaternion.identity);
bulletRigbd = Newbullet.GetComponent<Rigidbody2D>();
bulletRigbd.AddForce(Vector3.left * Force);
}
}
//停止开火动作
if(Input.GetKeyUp(KeyCode.U))
{
Anitor.SetBool("Attack", false);
}
//上楼梯
if (Input.GetKey(KeyCode.W)&&isclimb==true)
{
Anitor.SetBool("IsClimb", true);
transform.position += new Vector3(0, Vertical * moveSpeed * Time.deltaTime, 0);
}
//下楼梯
if (Input.GetKey(KeyCode.S) && isclimb == true)
{
transform.position += new Vector3(0, Vertical * moveSpeed * Time.deltaTime, 0);
}
//滑铲
if (Input.GetKeyDown(KeyCode.I) && !isJump)
{
isSlippery = true;
BoxCo2d.offset = new Vector2(0, -0.12f);
BoxCo2d.size= new Vector2(0.23869f, 0.18f);
if (DirectionRight)
{
Anitor.SetInteger("isSlippery", 1);
}
else
{
Anitor.SetInteger("isSlippery", -1);
}
}
JumpAnimation(); //空中动作处理
Slidingtackle();//滑铲移动
2.Ui设计
生命值通过开关调整,子弹数同单例的CreatePlayer中时时刻刻更新
3.视角跟随
通过组件Cinemachine实现(Unity没有就去下载Package Manager)
其中Cinemachine VirtualCamera是跟随的,Cinemachine Confiner 2d是移动范围,Mapd是需要自己创一个多边形碰撞器来划定区域。从而实现视角跟随的功能。
4.实验体Ai追击
这个设置的简单跟随,通过获取主角位置形成的方向来时刻移动。其中设定了距离和速度。
using UnityEngine;
using UnityEngine.U2D;
using UnityEngine.AI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonsterMovement : MonoBehaviour
{
public float attackrange=0.5f;
public float movespeed=3f;
public GameObject player;
public float Invincible_time=0.5f;
private BoxCollider2D Enemycollider;
private void Awake()
{
Enemycollider = GetComponent<BoxCollider2D>();
}
private void Update()
{
if(GameManeger.instance.isDeath)
{
Invoke("Invincible", 0.3f);
}else
Invincible();
}
void Invincible()
{
player = GameObject.FindGameObjectWithTag("Player");
if (Invincible_time < 0)
{
Enemycollider.enabled = true;
move();
}
Invincible_time-=Time.deltaTime;
}
void move()
{
Debug.Log("开始移动");
float dist = Vector3.Distance(player.transform.position, transform.position);
if (dist > attackrange)
{
transform.Translate(Vector3.right * movespeed * Time.deltaTime);
}
Vector2 direction = player.transform.position - transform.position;
Debug.Log(direction);
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
}
}
四、总结
该项目花了4天的时间吧,制作难点在动画控制和追击等方面。
遇到的问题1:子弹消失的声音无法触发
解决方法:用Destroy延时0.2f控制消失正常看不出
遇到的问题2:主角死亡,目标丢失错误
解决方法:用Invoke延时GameObject.Find主角对象
遇到的问题3:实验体玻璃罩被打破同时会打死里面刚出来的怪
解决方法:设置无敌方法,生成时无敌0.5秒但不能动。