@作者 : SYFStrive
@博客首页 : HomePage
:个人社区(欢迎大佬们加入) :社区链接
:觉得文章不错可以点点关注 :专栏连接
:程序员每天坚持锻炼
飞机大战专栏()
单例模式是1种设计模式:(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
单例使用说明:“单例模式是指在内存中只会创建一次对象的设计模式,并且确保一个类只有实例,而且会自行实例化,并向整个系统提供这个实例。
using UnityEngine;
//摘要:Base class for everything attached to GameObjects.
//Component中文说明:所有能挂载到游戏对象上的类型基类
public class Singleton : MonoBehaviour where T :Component
{
public static T Instance { get; private set; }
protected virtual void Awake()
{
Instance = this as T;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
//子弹的移动速度
[SerializeField] float moveSpeed;
//子弹的移动方向
[SerializeField] protected Vector3 moveDirection;
//子弹移动的Obj
protected GameObject targer;
protected virtual void OnEnable()
{
StartCoroutine(ProjectileMoveIE());
}
IEnumerator ProjectileMoveIE()
{
while (true)
{
//子弹移动
transform.position += moveSpeed * moveDirection * Time.deltaTime;
yield return null;
}
}
}
窗口如
说明:因为是工具脚本所以续成范型单例
视口脚本Viewport 如
using UnityEngine;
public class Viewport : Singleton
{
//限制player的镜头
private float maxX;
private float minX;
private float maxY;
private float minY;
private void Start()
{
//获取摄像机
Camera camera = Camera.main;
//屏幕坐标转换为世界坐标
Vector2 bottomLeft = camera.ViewportToWorldPoint(Vector3.zero);
Vector2 topRight = camera.ViewportToWorldPoint(Vector3.one);
//获取对应的X、Y值
maxX = topRight.x;
minX = bottomLeft.x;
maxY = topRight.y;
minY = bottomLeft.y;
}
///
/// 限制Player的坐标
///
/// 玩家位置
/// X的偏移量
/// Y的偏移量
///
public Vector3 AstrictPlayerPosition(Vector3 playerPosition,float paddingX,float paddingY)
{
//初始位置
Vector3 intaialPosition = Vector3.zero;
//Mathf.Clamp参数说明(值,最小值,最大值)
//paddingX、paddingY 限制飞机一半身体超出视口外偏移量
intaialPosition.x = Mathf.Clamp(playerPosition.x, minX+ paddingX, maxX- paddingX);
intaialPosition.y = Mathf.Clamp(playerPosition.y, minY+ paddingY, maxY- paddingY);
//返回位置
return intaialPosition;
}
}
实现共能: 添加系统事件 使系统事件与新输入系统绑定
添加代码如
using UnityEngine;
//运行时自动添加Rigidbody组件
[RequireComponent(typeof(Rigidbody2D))]
public class Player : MonoBehaviour
{
[Header("---Input---")]
[SerializeField]PlayerInput playerInput;
//获取刚体
private new Rigidbody2D rigidbody;
[Header("---Move---")]
//移动的速度
[SerializeField] float moveSpeed=10;
//限制飞机的一半身体超出视口
float paddingX;
float paddingY;
private void Awake()
{
//获取刚体组件
rigidbody=GetComponent();
}
private void Start()
{
//初始化重力为0
rigidbody.gravityScale = 0f;
//初始化激活动作表
playerInput.AstrictImport();
//玩家的尺度
//GetComponent().sharedMesh.bounds.size获得的是未经缩放的大小。
//GetComponent().bounds.size获得是是经过缩放后的大小。
var size = transform.GetChild(0).GetComponent().bounds.size;
paddingX = size.x / 2;
paddingY = size.y / 2;
}
private void OnEnable()
{
//订阅事件
playerInput.onMove += Move;
playerInput.onStopMove += StopMove;
}
private void OnDisable()
{
//移除事件
playerInput.onMove -= Move;
playerInput.onStopMove -= StopMove;
}
///
/// 移动
///
private void Move(Vector2 moveInput)
{
//好理解先接受移动的值
var moveSpeedS = moveInput * moveSpeed;
//刚体移动
rigidbody.velocity= moveSpeedS;
}
///
/// 停止移动
///
private void StopMove()
{
//刚体移动
rigidbody.velocity = Vector3.zero;
//停止携程(限制范围)
StopCoroutine("AstrictPlayerPositionIE");
}
///
/// 移动
///
private void Move(Vector2 moveInput)
{
//好理解先接受移动的值
var moveSpeedS = moveInput * moveSpeed;
//刚体移动
rigidbody.velocity= moveSpeedS;
//开启携程(限制范围)
StartCoroutine("AstrictPlayerPositionIE");
}
//限制飞机的位置 方法:1、可以在Update调用(消耗性能的神) 2、可以在携程调用(这里使用携程)
IEnumerator AstrictPlayerPositionIE()
{
while (true)
{
transform.position = Viewport.Instance.AstrictPlayerPosition(transform.position, paddingX, paddingY);
yield return null;
}
}
}
效果如
实现共能: 实现加速与减速携程
添加代码如
using UnityEngine;
//运行时自动添加Rigidbody组件
[RequireComponent(typeof(Rigidbody2D))]
public class Player : MonoBehaviour
{
[Header("---Input---")]
[SerializeField]PlayerInput playerInput;
//获取刚体
private new Rigidbody2D rigidbody;
[Header("---Move---")]
//移动的速度
[SerializeField] float moveSpeed = 10;
//限制飞机的一半身体超出视口
float paddingX;
float paddingY;
//飞机的加速与减速时间
[SerializeField] float speedUpTime = 3;
[SerializeField] float speedCutTime = 3;
//飞机移动旋转的角度
[SerializeField] float playerMoveRosition = 10;
//防止被刚体碰到短暂停止BUG
private Vector2 moveDirection;
//玩家移动旋转的初始化值 防止频繁触发GC
private float t;
private Vector2 moveVelocity;
private Quaternion moveQuaternion;
private WaitForFixedUpdate moveWaitForFixedUpdate = new WaitForFixedUpdate();
[Header("---停止待参数的携程---")]
//停止携程的第三种方法
private Coroutine moveCoroutine;
private Coroutine relfRecoverCoroutine;
private void Awake()
{
//获取刚体组件
rigidbody=GetComponent();
}
private void Start()
{
//初始化重力为0
rigidbody.gravityScale = 0f;
//初始化激活动作表
playerInput.AstrictImport();
//视口的尺度
//GetComponent().sharedMesh.bounds.size获得的是未经缩放的大小。
//GetComponent().bounds.size获得是是经过缩放后的大小。
var size = transform.GetChild(0).GetComponent().bounds.size;
paddingX = size.x / 2;
paddingY = size.y / 2;
}
private void OnEnable()
{
//订阅事件
playerInput.onMove += Move;
playerInput.onStopMove += StopMove;
}
private void OnDisable()
{
//移除事件
playerInput.onMove -= Move;
playerInput.onStopMove -= StopMove;
}
#region Move
///
/// 玩家移动
///
private void Move(Vector2 moveInput)
{
//再次移动前应该停止之前的携程(使用第三种参数停止携程)
if (moveCoroutine != null)
StopCoroutine(moveCoroutine);
好理解先接受移动的值
//var moveSpeedS = moveInput * moveSpeed;
刚体移动
//rigidbody.velocity= moveSpeedS;
//移动的初始值
moveDirection = moveInput.normalized;
//获取旋转的值
Quaternion moveRosition = Quaternion.AngleAxis(playerMoveRosition * moveInput.y, Vector3.right);
//开启携程(限制加速减速)
moveCoroutine = StartCoroutine(PlayerMoveCoroutine(speedUpTime, moveDirection * moveSpeed, moveRosition));
//开启携程(限制范围)
stopMoveCoroutine = StartCoroutine(nameof(AstrictPlayerPositionIE));
}
///
/// 停止移动
///
private void StopMove()
{
//再次移动前应该停止之前的携程(使用第三种参数停止携程)
if (moveCoroutine != null)
StopCoroutine(moveCoroutine);
刚体移动
//rigidbody.velocity = Vector3.zero;
//停止携程(限制加速减速)
moveDirection = Vector3.zero;
moveCoroutine = StartCoroutine(PlayerMoveCoroutine(speedCutTime, moveDirection, Quaternion.identity));
//停止携程(限制范围)
StopCoroutine(stopMoveCoroutine);
}
//限制飞机的位置 方法:1、可以在Update调用(消耗性能的神) 2、可以在携程调用(这里使用携程)
IEnumerator AstrictPlayerPositionIE()
{
while (true)
{
transform.position = Viewport.Instance.AstrictPlayerPosition(transform.position, paddingX, paddingY);
yield return null;
}
}
///
/// 加速与减速携程
///
/// 加速的时间
/// 移动的目标位置
/// 旋转的目标位置
///
IEnumerator PlayerMoveCoroutine(float time, Vector2 moveTarget, Quaternion rositionTarget)
{
t = 0f;
//初始化移动速度
moveVelocity = rigidbody.velocity;
//初始化旋转角度
moveQuaternion = transform.rotation;
while (t < 1f)
{
t += Time.fixedDeltaTime / time;
//lerp移动体验极佳手感
rigidbody.velocity = Vector2.Lerp(moveVelocity, moveTarget, t);
//玩家移动旋转
transform.rotation = Quaternion.Lerp(moveQuaternion, rositionTarget, t);
//空返回
yield return moveWaitForFixedUpdate;
}
}
#endregion
///
/// 停止移动
///
private void StopMove()
{
//再次移动前应该停止之前的携程(使用第三种参数停止携程)
if (moveCoroutine != null)
StopCoroutine(moveCoroutine);
刚体移动
//rigidbody.velocity = Vector3.zero;
刚体移动
//rigidbody.velocity = Vector3.zero;
//停止携程(限制加速减速)
moveDirection = Vector3.zero;
moveCoroutine = StartCoroutine(PlayerMoveCoroutine(speedCutTime, moveDirection, Quaternion.identity));
//停止携程(限制范围)
StopCoroutine(stopMoveCoroutine);
}
}
相机处理如
添加后处理效果
说明:当主摄像机碰到局部Volume对象的碰撞体后就会应用这个局部的镜头变形效果。
使用场景:水波纹等效果。
后处理参数如
实现:每按下时发射子弹
using UnityEngine;
public class PlayerProjectile : Projectile
{
}
public class Player : MonoBehaviour
{
[Header("---Fire---")]
//子弹的预制体
[SerializeField] GameObject ProjectileTOP90;
[SerializeField] GameObject ProjectileTOP;
[SerializeField] GameObject ProjectileCenter;
[SerializeField] GameObject ProjectileDown;
[SerializeField] GameObject ProjectileDown90;
//子弹模式
[SerializeField, Range(0, 4)] int attackPattern = 0;
//发射的位置
[SerializeField] Transform fireTranPosTop90;
[SerializeField] Transform fireTranPosCenter;
[SerializeField] Transform fireTranPosTop;
[SerializeField] Transform fireTranPosDown;
[SerializeField] Transform fireTranPosDown90;
//发射子弹的间隔
[SerializeField] float fireTime = 0.3f;
//发射子弹间隔携程
WaitForSeconds fireProjectileTimeIE;
//生命自动恢复的间隔携程
WaitForSeconds selfRecoverTimeIE;
//使用技能下的开火时间携程
WaitForSeconds areSkillFireProjectileTimeIE;
//发射子弹携程
IEnumerator FireProjectileIE()
{
//创建预制体
while (true)
{
Instantiate(projectile1, fireTranPosCenter.position, Quaternion.identity);
//协程间隔 判断是否是仅能子弹
yield return isEnetgySkill ? areSkillFireProjectileTimeIE : fireProjectileTimeIE;
}
}
}
ProjectileDestroy 实现如
using System.Collections;
using UnityEngine;
public class ProjectileDestroy : MonoBehaviour
{
//删除或隐藏的间隔时间
[SerializeField] float destroyTimer=1.3f;
//是否删除
[SerializeField] bool isDestroy;
//删除的子弹的间隔携程
[SerializeField] WaitForSeconds destroyTime;
private void Awake()
{
//初始化
destroyTime = new WaitForSeconds(destroyTimer);
}
private void OnEnable()
{
//显示时执行携程
StartCoroutine(DestroyProjectile());
}
IEnumerator DestroyProjectile()
{
yield return destroyTime;
if (isDestroy)
{
Destroy(gameObject);
}
else
{
gameObject.SetActive(false);
}
}
}
本文到这里就结束了,大佬们的支持是我持续更新的最大动力,希望这篇文章能帮到大家相关专栏连接
下篇文章再见ヾ( ̄▽ ̄)ByeBye