005_添加动画、子弹碰撞、无敌时间
RubyController
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.PlayerLoop;
using UnityEngine.UIElements;
using UnityEngine.WSA;
public class RubyController : MonoBehaviour {
//子弹预制件对象
public GameObject cogBulletPrefab;
//无敌时间
public float invincibleTime = 2.0f;
//无敌时间计时器
public float invincibleTimer;
//是否无敌的标志
bool isInvincible;
//最大生命值
public int maxHealth = 5;
//C#中支持面向对象程序设计中的封装概念,对数据成员的保护
//数据成员变量,默认一般都应该设置为私有,只能通过当前类的方法或属性进行访问
//属性是公有的,可以通过取值器get、赋值器 set设定对应字段的访问规则,满足规则才能够访问
public int health {
get { return currentHealth; }
//set { currentHealth = value; }
}
//当前生命值
int currentHealth;
// 将速度暴露出来,使其可调
public float speed = 4f;
//声明刚体对象
Rigidbody2D rigidbody2D;
//获取用户输入
public float horizontal = 0f;
public float vertical = 0f;
//动画管理组件
Animator animator;
Vector2 move;
// 在第一次帧更新之前调用 Start
private void Start() {
//获取当前游戏对象的刚体组件
rigidbody2D = GetComponent<Rigidbody2D>();
//游戏开始,玩家满血
currentHealth = 3;
Debug.Log($"currentHealth:{currentHealth}");
move = new Vector2(1, 0);
animator = GetComponent<Animator>();
}
// 每帧调用一次 Update
void Update() {
/* 根据按键移动上下左右的位置:每帧移动0.1 */
//获取水平输入,按向左会获得-1.0f,按向右会获得1.0f
horizontal = Input.GetAxis("Horizontal");
//获取垂直输入按向下会获得-1.0f,按向上会获得1.0f
vertical = Input.GetAxis("Vertical");
if (!Mathf.Approximately(horizontal, 0f) || !Mathf.Approximately(vertical, 0f)) {
move = new Vector2(horizontal, vertical);
move.Normalize();
animator.SetFloat("Look X", move.x);
animator.SetFloat("Look Y", move.y);
animator.SetFloat("Speed", move.magnitude);
} else {
animator.SetFloat("Speed", 0);
}
//是否处于无敌状态
if (isInvincible) {
//无敌计数器减去一帧的时间
invincibleTimer -= Time.deltaTime;
if (invincibleTimer < 0) {
isInvincible = false;
}
}
//按住Shift加快移速
if(Input.GetKeyDown(KeyCode.LeftShift)) {
speed = 8f;
} else if(Input.GetKeyUp(KeyCode.LeftShift)) {
speed = 4f;
}
//按下鼠标左键发射子弹
if (Input.GetMouseButtonDown(0)) {
Launch();
}
}
//固定时间间隔执行的更新方法
private void FixedUpdate() {
//获取对象当前位置
Vector2 position = rigidbody2D.position;
//更改位置,Time.deltaTime 每帧的时间间隔,float 类型
position.x = position.x + speed * horizontal * Time.deltaTime;
position.y = position.y + speed * vertical * Time.deltaTime;
//新位置给游戏对象
rigidbody2D.position = position;
}
//更改生命值的方法
public void ChangeHealth(int amount) {
if (amount < 0) {
animator.SetTrigger("Hit");
if (isInvincible) {
return;
}
isInvincible = true;
invincibleTimer = invincibleTime;
}
//限制方法,限制当前生命值的赋值范围:0~最大生命值
currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
Debug.Log("当前生命值:" + currentHealth + "/" + maxHealth);
}
private void Launch() {
//创建子弹游戏对象
GameObject cogBulletObject = Instantiate(cogBulletPrefab, rigidbody2D.position + Vector2.up * 0.5f, Quaternion.identity);
//获取子弹游戏对象的脚步组件
CogBulletController cogBullet = cogBulletObject.GetComponent<CogBulletController>();
//通过脚步对象调用子弹移动的方法
//params:移动的方向,力
cogBullet.Launch(move, 600);
//发射动画
animator.SetTrigger("Launch");
}
}
EnemyController
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class EnemyController : MonoBehaviour {
//每次掉血量
public int damageNum = -1;
//敌人移动速度
public float speed = 3f;
//声明刚体对象
Rigidbody2D rigidbody2D;
//移动方向
public float horizontal = 0;
public float vertical = 1;
//移动时间
public float moveTime = 3;
//移动计时器
float moveTimer;
//动画管理组件
Animator animator;
//robot是否修复
bool repaired;
private void Start() {
rigidbody2D = GetComponent<Rigidbody2D>();
moveTimer = moveTime;
animator = GetComponent<Animator>();
}
private void Update() {
//如果robot已修复,就不再移动
if (repaired) {
return;
}
moveTimer -= Time.deltaTime;
if (moveTimer < 0) {
vertical *= -1;
horizontal *= -1;
moveTimer = moveTime;
}
}
//固定时间间隔执行的更新方法
private void FixedUpdate() {
//如果robot已修复,就不再移动
if (repaired) {
return;
}
//获取对象当前位置
Vector2 position = rigidbody2D.position;
//更改位置,Time.deltaTime 每帧的时间间隔,float 类型
position.x = position.x + speed * horizontal * Time.deltaTime;
position.y = position.y + speed * vertical * Time.deltaTime;
//新位置给游戏对象
rigidbody2D.position = position;
animator.SetFloat("Move X", position.x);
animator.SetFloat("Move Y", position.y);
}
//刚体碰撞事件方法
private void OnCollisionEnter2D(Collision2D collision) {
RubyController rubyController = collision.gameObject.GetComponent<RubyController>();
if (rubyController != null) {
rubyController.ChangeHealth(damageNum);
}
}
public void Fix() {
//robot已修复
repaired = true;
//让robot不再受碰撞,刚体对象取消物理引擎效果
rigidbody2D.simulated = false;
//播放修复后的动画
animator.SetTrigger("Fixed");
}
}
CogBulletController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CogBulletController : MonoBehaviour {
Rigidbody2D rigidbody2D;
// Start is called before the first frame update
void Start() {
}
private void Awake() {
rigidbody2D = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update() {
//飞行距离超过100单位后,自动销毁
if(transform.position.magnitude > 100f) {
Destroy(gameObject);
}
}
//direction:方向,force:力
public void Launch(Vector2 direction, float force) {
//对游戏对象施加一个力,使其移动
rigidbody2D.AddForce(direction * force);
}
private void OnCollisionEnter2D(Collision2D collision) {
//获取子弹碰撞到的游戏对象脚步组件
EnemyController enemyController = collision.gameObject.GetComponent<EnemyController>();
if (enemyController != null) {
enemyController.Fix();
}
//打印子弹碰撞到的游戏对象
Debug.Log($"齿轮子弹碰撞到了: {collision.gameObject}");
//销毁子弹
Destroy(gameObject);
}
}
DamageeZone
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DamageZone : MonoBehaviour
{
//每次掉血量
public int damageNum = -1;
//刚体在触发器内的每一帧都会调用此函数,而不是在刚体刚进入时仅调用一次。
private void OnTriggerStay2D(Collider2D collision)
{
RubyController rubyController = collision.gameObject.GetComponent<RubyController>();
if(rubyController != null )
{
rubyController.ChangeHealth(damageNum);
}
}
}