Unity使用新输入系统InputSystem制作飞机大战Demo(对象池设计模式及应用)

这篇具有很好参考价值的文章主要介绍了Unity使用新输入系统InputSystem制作飞机大战Demo(对象池设计模式及应用)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

输入系统 设计模式,unity,设计模式,单例模式

@作者 : SYFStrive

@博客首页 : HomePage

📌:个人社区(欢迎大佬们加入) 👉:社区链接🔗

📌:觉得文章不错可以点点关注 👉:专栏连接🔗

💃:程序员每天坚持锻炼💪

输入系统 设计模式,unity,设计模式,单例模式
输入系统 设计模式,unity,设计模式,单例模式
输入系统 设计模式,unity,设计模式,单例模式

👉 飞机大战专栏(🔥)

游戏单例脚本

单例模式是1种设计模式:👉(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

单例使用说明:“单例模式是指在内存中只会创建一次对象的设计模式,并且确保一个类只有实例,而且会自行实例化,并向整个系统提供这个实例。

非持久化泛型单例

using UnityEngine;

//摘要:Base class for everything attached to GameObjects.
//Component中文说明:所有能挂载到游戏对象上的类型基类
public class Singleton<T> : 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;
        }
    }
}

对象池制作

思路:从池中取出一个可用对象(判断有没有可用的对象、如果有就出列,没有就克隆1个) 👉 启动可用对象池(显示改对象) 👉 让完成任务的对象返回对象池(进列)

对象池步骤:克隆对象 👉 初始话对象池 👉 可用队列&&返回队列 👉预备好的对象

代码框架

代码如 👇

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

//序列化Pool
[System.Serializable()]public class Pool
{
  //初始化对象池的个数 👉 测试初始化需要多少个预制体
  public int initializeSize => size;
  //需要的总个数 👉 测试初始化需要多少个预制体
  public int sumSize => queue.Count;

  //返回prefabeObjNmae
  public GameObject prefabeObjProperty=> prefabeObj;
  //初始化对象池的个数
  public int initializeSize => size;
  //创建队列
  private Queue<GameObject> queue;
  //对象池用的Obj
  [SerializeField] GameObject prefabeObj;
  //初始化的个数
  [SerializeField] int objCount;
  //设置父对象的位置
  private Transform parentTran;
}

1、克隆对象

代码如 👇

  /// <summary>
  /// 克隆对象
  /// </summary>
  private GameObject CloneObj()
  {
    //创建对象
    var cloneObj = GameObject.Instantiate(prefabeObj,parentTran);
    //隐藏对象
    cloneObj.SetActive(false);
    //返回对象
    return cloneObj;
  }

2、初始话对象池

代码如 👇

  /// <summary>
  /// 初始话对象池
  /// </summary>
  private void Initialize(Transform parentTran)
  {
    //保存parentTran位置
    this.parentTran = parentTran;

    //初始化队列否者会是空值
    queue = new Queue<GameObject>();

    //遍历创建Obj添加进队列
    for (int i = 0; i < objCount; i++)
    {
      queue.Enqueue(CloneObj());
    }
  }

3、可用队列

代码如 👇

  /// <summary>
  /// 可用多列
  /// </summary>
  private GameObject AvailableQueue()
  {
    GameObject availableObj;
    
    //return queue.Count > 0 ? queue.Dequeue() : CloneObj();
    //出列 👉 想要出列后直接进列必须先判断第一个是否处于激活状态,否者去除第二个可能是出列的状态
    //poll:将首个元素从队列中弹出,如果队列是空的,就返回null
	//peek:查看首个元素,不会移除首个元素,如果队列是空的就返回null
	//element:查看首个元素,不会移除首个元素,如果队列是空的就抛出异常NoSuchElementException
    
    if (queue.Count > 0 && !queue.Peek().activeSelf)
      availableObj = queue.Dequeue();
    else
      availableObj = CloneObj();

    //进列
    queue.Enqueue(availableObj);

    //返回obj
    return availableObj;
  }

4、预备好的对象

代码如 👇

  #region 预备的对象&&重载
  /// <summary>
  /// 预备好的对象
  /// </summary>
  private GameObject PrepareQuene(Vector3 position)
  {
    GameObject prepareObj = AvailableQueue();
    prefabeObj.SetActive(true);
    prefabeObj.transform.position = position;
    return prefabeObj;
  }
  private GameObject PrepareQuene(Vector3 position,Quaternion quaternion)
  {
    GameObject prepareObj = AvailableQueue();
    prefabeObj.SetActive(true);
    prefabeObj.transform.position = position;
    prefabeObj.transform.rotation = quaternion;
    return prefabeObj;
  }
  private GameObject PrepareQuene(Vector3 position, Quaternion quaternion, Vector3 localScale)
  {
    GameObject prepareObj = AvailableQueue();
    prefabeObj.SetActive(true);
    prefabeObj.transform.position = position;
    prefabeObj.transform.rotation = quaternion;
    prefabeObj.transform.localScale = localScale;
    return prefabeObj;
  }

  #endregion

5、对象池管理脚本

public class PoolManager : MonoBehaviour
{
  //储存不同类装备的对象池
  [SerializeField] Pool[] poolArr;

  private void OnEnable()
  {
    InitializeObj(poolArr);
  }

  /// <summary>
  /// 初始化子弹
  /// </summary>
  private void InitializeObj(Pool[] pools)
  {
    foreach (var pool in pools)
    {
      //给创建的Obj命名
      Transform poolPatent = new GameObject("对象池Poll" + pool.prefabeName.name).transform;
      //设置父位置
      poolPatent.parent = transform;
      //初始话对象池
      pool.Initialize(poolPatent);
    }
  }
}

对象池的应用

字典Dictionary:对象池的预制体(Key键) 👉 字典(获取对应Key的值) 👉从对象池Pool检索 👉 匹配对应的数据

poolManager添加

添加如 👇

using System.Collections;
using System.Collections.Generic;
using System.Security.Policy;
using UnityEngine;

public class PoolManager : MonoBehaviour
{
    //储存不同类装备的对象池
    [SerializeField] Pool[] poolArr;

    //使用字典来存储不同的装备
    public static Dictionary<GameObject, Pool> dictionary;

    private void Awake()
    {
        //实例化字典
        dictionary = new Dictionary<GameObject, Pool>();
    }

    private void OnEnable()
    {
        InitializeObj(poolArr);
    }
    
    #region 测试代码
		
		#if UNITY_EDITOR
		
		    //停止游戏时执行
		    private void OnDestroy()
		    {
		        CheckPoolSize(poolArr);
		    }
		    
		#endif

    #endregion

    #region 测试:需要对象池的大小容量
    private void CheckPoolSize(Pool[] pools)
    {
        foreach (Pool pool in pools)
        {
            if (pool.sumSize > pool.initializeSize)
            {
                Debug.LogWarning(string.Format("Pool该预制体的:{0}初始大小为{1},需要的大小为{2}",
                    pool.prefabeObjProperty.name,
                    pool.initializeSize,
                    pool.sumSize));
            }
        }
    }
    #endregion

    /// <summary>
    /// 初始化子弹
    /// </summary>
    private void InitializeObj(Pool[] pools)
    {
        foreach (var pool in pools)
        {
        #region //条件编译操作 只有在Unity引起运行
			#if UNITY_EDITOR
	            if (dictionary.ContainsKey(pool.prefabeObjProperty))
	            {
	                Debug.Log("字典有相同的名字!");
	                continue;
	            }
			#endif
        #endregion

            //添加到字典
            dictionary.Add(pool.prefabeObjProperty, pool);
            //给创建的Obj命名
            Transform poolPatent = new GameObject("对象池Poll" + pool.prefabeObjProperty.name).transform;
            //设置父位置
            poolPatent.parent = transform;
            //初始话对象池
            pool.Initialize(poolPatent);
        }
    }

    #region  释放子弹&&重载
    /// <summary>
    /// 释放子弹
    /// </summary>
    /// <param name="prefabe">指定游戏的预制体</param>
    /// <returns></returns>
    public static GameObject Release(GameObject prefabe)
    {
        #region 条件编译操作 只有在Unity引起运行
			#if UNITY_EDITOR
		        if (!dictionary.ContainsKey(prefabe))
		        {
		            Debug.Log("找不到对应的Key");
		            return null;
		        }
			#endif
       #endregion

        return dictionary[prefabe].PrepareQuene();
    }

    /// <summary>
    /// 释放子弹
    /// </summary>
    /// <param name="prefabe">指定游戏的预制体</param>
    /// <param name="position">指定游戏的位置</param>
    /// <returns></returns>
    public static GameObject Release(GameObject prefabe, Vector3 position)
    {
        #region 条件编译操作 只有在Unity引起运行
			#if UNITY_EDITOR
		        if (!dictionary.ContainsKey(prefabe))
		        {
		            Debug.Log("找不到对应的Key");
		            return null;
		        }
			#endif
       #endregion

        #endregion
        return dictionary[prefabe].PrepareQuene(position);
    }


    /// <summary>
    /// 释放子弹
    /// </summary>
    /// <param name="prefabe">指定游戏的预制体</param>
    /// <param name="position">指定游戏的位置</param>
    /// <param name="quaternion">指定游戏的旋转位置</param>
    /// <returns></returns>
    public static GameObject Release(GameObject prefabe, Vector3 position, Quaternion quaternion)
    {
        #region 条件编译操作 只有在Unity引起运行
			#if UNITY_EDITOR
		        if (!dictionary.ContainsKey(prefabe))
		        {
		            Debug.Log("找不到对应的Key");
		            return null;
		        }
			#endif
       #endregion

        return dictionary[prefabe].PrepareQuene(position, quaternion);
    }


    /// <summary>
    /// 释放子弹
    /// </summary>
    /// <param name="prefabe">指定游戏的预制体</param>
    /// <param name="position">指定游戏的位置</param>
    /// <param name="quaternion">指定游戏的旋转位置</param>
    /// <param name="localscale">指定游戏的旋转缩放</param>
    /// <returns></returns>
    public static GameObject Release(GameObject prefabe, Vector3 position, Quaternion quaternion, Vector3 localscale)
    {
        #region 条件编译操作 只有在Unity引起运行
			#if UNITY_EDITOR
		        if (!dictionary.ContainsKey(prefabe))
		        {
		            Debug.Log("找不到对应的Key");
		            return null;
		        }
			#endif
       #endregion

        return dictionary[prefabe].PrepareQuene(position, quaternion, localscale);
    }
    
    #endregion
}

Player添加功能

添加如 👇

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 areSkillFireProjectileTimeIE;
	  
	  [Header("---EnergySkill---")]
	  //是否开启了爆发技能
	  private bool isEnetgySkill;

  protected override void OnEnable()
  {
    base.OnEnable();

    //订阅移动事件
    playerInput.onMove += Move;
    playerInput.onStopMove += StopMove;

    //订阅发射子弹
    playerInput.onFire += Fire;
    playerInput.onStopFire += StopFire;
  }
  private void OnDisable()
  {
    //移除移动事件
    playerInput.onMove -= Move;
    playerInput.onStopMove -= StopMove;

    //移除发射子弹
    playerInput.onFire -= Fire;
    playerInput.onStopFire -= StopFire;
  }



  private void Start()
  {
    //实例化子弹协程时间间隔
    fireProjectileTimeIE = new WaitForSeconds(fireTime);
    //使用技能下的开火时间
    areSkillFireProjectileTimeIE = new WaitForSeconds(fireTime / areSkillPlayerProjectilefFactorAdd);
  }

  #region 子弹
  /// <summary>
  /// 发射子弹
  /// </summary>
  private void Fire()
  {
    StartCoroutine(nameof(FireProjectileIE));
  }
  /// <summary>
  ///停止发射
  /// </summary>
  private void StopFire()
  {
    StopCoroutine(nameof(FireProjectileIE));
  }

  //发射子弹携程
  IEnumerator FireProjectileIE()
  {
    //创建预制体
    while (true)
    {
      switch (attackPattern)
      {
        case 0:
          //普通创建子弹
          //Instantiate(projectile1, fireTranPosCenter.position, Quaternion.identity);

          //对象池方法
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileCenter, fireTranPosCenter.position);

          break;
        case 1:
          //普通创建子弹
          //Instantiate(projectile1, fireTranPosCenter.position, Quaternion.identity);
          //Instantiate(projectile2, fireTranPosTop.position, Quaternion.identity);

          //对象池方法
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileCenter, fireTranPosCenter.position);
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileTOP, fireTranPosTop.position);
          break;
        case 2:
          //普通创建子弹
          //Instantiate(projectile1, fireTranPosCenter.position, Quaternion.identity);
          //Instantiate(projectile2, fireTranPosTop.position, Quaternion.identity);
          //Instantiate(projectile3, fireTranPosDown.position, Quaternion.identity);

          //对象池方法
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileCenter, fireTranPosCenter.position);
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileTOP, fireTranPosTop.position);
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileDown, fireTranPosDown.position);
          break;
        case 3:
          //对象池方法
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileCenter, fireTranPosCenter.position);
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileTOP, fireTranPosTop.position);
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileDown, fireTranPosDown.position);
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileTOP90, fireTranPosTop90.position);
          break;
        case 4:
          //对象池方法
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileCenter, fireTranPosCenter.position);
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileTOP, fireTranPosTop.position);
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileDown, fireTranPosDown.position);
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileTOP90, fireTranPosTop90.position);
          PoolManager.Release(isEnetgySkill ? energyPrefabeVFX : ProjectileDown90, fireTranPosDown90.position);
          break;
      }
      //播放声音
      AudioManager.Instance.PlaySFX(audioData);

      //判断是否是技能子弹 👉 条用不同的携程时间
      yield return isEnetgySkill ? areSkillFireProjectileTimeIE : fireProjectileTimeIE;
    }
  }
  #endregion
}

测试子弹对象池需要的数量

效果如 👇

输入系统 设计模式,unity,设计模式,单例模式

子弹尾线出现残影的问题

  using UnityEngine;

  public class PlayerProjectile : Projectile
  {
   private TrailRenderer trilRenderer;

    protected virtual void Awake()
    {
        //获取对应的组件   
        trilRenderer=GetComponentInChildren<TrailRenderer>();
        if (moveDirection != Vector3.right)
        {
            transform.GetChild(0).rotation = Quaternion.FromToRotation(Vector3.right, moveDirection);
        }
    }
    //被禁用调用
    private void OnDisable()
    {
        //清楚拖尾 
        trilRenderer.Clear();
    }
}

效果如 👇

输入系统 设计模式,unity,设计模式,单例模式

敌人控制器制作

实现:完成敌人生成初始点、随机生成,发射子弹

控制敌人的飞行范围

Viewport 视图添加代码如 👇

using UnityEngine;

public class Viewport : Singleton<Viewport>
{
    //获取X轴的中间位置
    private float centerPosX;
    
    private void Start()
    {
        //获取X轴的中间位置
        centerPosX = camera.ViewportToWorldPoint(new Vector3(0.5f, 0f, 0f)).x;
    }

    /// <summary>
    /// 敌人随机的初始化位置
    /// </summary>
    public Vector3 RandomEnemyInitializePos(float paddingX,float paddingY)
    {
        //初始化位置
        Vector3 intaialPosition = Vector3.zero;

        //paddingX、paddingY 限制飞机一半身体超出视口外偏移量
        intaialPosition.x = maxX + paddingX;
        intaialPosition.y = Random.Range(minY + paddingY, maxY - paddingY);

        //返回位置
        return intaialPosition;
    }


    /// <summary>
    /// 限制敌人的移动范围
    /// </summary>
    /// <returns></returns>
    public Vector3 EnemyRandomMoveScope(float paddingX, float paddingY)
    {
        //初始化位置
        Vector3 MoveScopePosition = Vector3.zero;
        //paddingX、paddingY 限制飞机一半身体超出视口外偏移量
        MoveScopePosition.x = Random.Range(centerPosX,maxX-paddingX);
        MoveScopePosition.y = Random.Range(minY + paddingY, maxY - paddingY);
        //返回位置
        return MoveScopePosition;
    }

    /// <summary>
    /// 限制敌人的移动范围
    /// </summary>
    /// <returns></returns>
    public Vector3 EnemyRandomMove(float paddingX, float paddingY)
    {
        //初始化位置
        Vector3 MoveScopePosition = Vector3.zero;
        //paddingX、paddingY 限制飞机一半身体超出视口外偏移量
        MoveScopePosition.x = Random.Range(minX + paddingX, maxX - paddingX);
        MoveScopePosition.y = Random.Range(minY + paddingY, maxY - paddingY);
        //返回位置
        return MoveScopePosition;
    }
}

控制敌人的移动发射子弹

EnemyController 敌人管理器添加代码如 👇

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

public class EnemyController : MonoBehaviour
{
    [Header("---Move---")]
    [SerializeField] float paddingX;
    [SerializeField] float paddingY;
    [SerializeField] float moveSpeed = 2f;
    [SerializeField] float rositionAngle = 25f;

    [Header("---Fire---")]
    [SerializeField] float maxFireTime=2;
    [SerializeField] float minFireTime=3;
    [SerializeField] GameObject[] enemyProjectileS;
    [SerializeField] Transform enemyFirePosition;

    private void OnEnable()
    {
        //敌人随机移动携程
        StartCoroutine(nameof(EnemyRandomMovePosIE));
        //开启敌人射击携程
        StartCoroutine(nameof(EnemyRandomFireIE));
    }

    private void OnDisable()
    {
        //关闭所有携程
        StopAllCoroutines();
    }

    IEnumerator EnemyRandomMovePosIE()
    {
        //敌人初始化的位置
        transform.position = Viewport.Instance.RandomEnemyInitializePos(paddingX, paddingY);
        //初始化移动目标的位置
        Vector3 targetPosition = Viewport.Instance.EnemyRandomMoveScope(paddingX, paddingY);

        while (gameObject.activeSelf)
        {
            //PseudoCode伪代码(思路清晰)
            //敌人还没到达目标位置 那么继续移动
            //Mathf.Epsilon 接近与零的数
            if (Vector3.Distance(transform.position, targetPosition) > Mathf.Epsilon)
            {
                //移动
                transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
                //旋转
                transform.rotation = Quaternion.AngleAxis((targetPosition - transform.position).normalized.y * rositionAngle, Vector3.right);
            }
            else
                //如果敌人到达了目标位置那么继续寻找一个新的目标移动
                targetPosition = Viewport.Instance.EnemyRandomMoveScope(paddingX, paddingY);
            yield return null;
        }
    }

    IEnumerator EnemyRandomFireIE()
    {
        while (gameObject.activeSelf)
        {
            yield return new WaitForSeconds(Random.Range(minFireTime, maxFireTime));
            foreach (var enemyProjectile in enemyProjectileS)
            {
                //使用对象池
                PoolManager.Release(enemyProjectile, enemyFirePosition.position);
            }
        }
    }
}

敌人子弹脚本

using UnityEngine;

public class EnemyProjectile : Projectile
{
    private void Awake()
    {
        if(moveDirection != Vector3.left)
        {
            transform.rotation = Quaternion.FromToRotation(Vector3.left, moveDirection);
        }    
    }
}

添加敌人子弹的对象池

PoolManager添加代码如 👇

    [SerializeField] Pool[] enemyPoolProjectile;
    
    private void OnEnable()
    {
        //初始化对象池
        InitializeObj(enemyPoolProjectile);
    }
    #region 测试代码
		#if UNITY_EDITOR
	    //停止游戏时执行
	    private void OnDestroy()
	    {
	        CheckPoolSize(enemyPoolProjectile);
	    }
		#endif
    #endregion

效果

输入系统 设计模式,unity,设计模式,单例模式

最后

输入系统 设计模式,unity,设计模式,单例模式
本文到这里就结束了,大佬们的支持是我持续更新的最大动力,希望这篇文章能帮到大家💪

 

                 相关专栏连接🔗
输入系统 设计模式,unity,设计模式,单例模式

下篇文章再见ヾ( ̄▽ ̄)ByeBye

输入系统 设计模式,unity,设计模式,单例模式文章来源地址https://www.toymoban.com/news/detail-818506.html

到了这里,关于Unity使用新输入系统InputSystem制作飞机大战Demo(对象池设计模式及应用)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity全新的输入系统InputSystem

    在Unity中,默认使用的是旧的输入管理器(InputSystemOld) 在脚本中,利用Input类可以获得用户的输入操作,以及访问移动设备的多点触控或加速感应数据,Input类可以读取输入管理器中设置的按键,在Updata函数中监测用户的输入。 1.虚拟轴 在项目设置中可以看到虚拟轴的相关设

    2024年02月05日
    浏览(42)
  • Unity之新版输入系统InputSystem入门

    最近Unity版本全面升级到Unity2021了,着色器也全面使用URP,接下来毫无疑问,输入系统也要全面升级InputSystem,这也是Unity官方希望我们做的,毕竟现在都2023年了,我们的技术是需要跟上时代的步伐。 老版本的InputSysten系统,其实就一个Input静态类,官方给我们预定了一些常用

    2024年02月16日
    浏览(30)
  • Unity之新版输入系统InputSystem如何自定义InputActions

    上一篇文章,我们介绍了如何使用新版本的InputSystem,我们知道了InputActionsAsset给我们提供了更多的灵活性,扩展性和复用性。那么这篇文章我们就来介绍一下如何创建自定义InputActionAsset Input Action Asset 包含输入 Actions及其关联的Bindings和Control Schemes 的资源。这些资源文件扩展

    2024年02月11日
    浏览(38)
  • python---简单游戏制作(飞机大战)

    1.开发软件 pycharm 编程软件 pygame 第三方库 sprite Group 2.技术介绍      pycharm: PyCharm是一种Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制。此外,该IDE提供

    2024年02月12日
    浏览(38)
  • 【python】 pygame学习示例 --飞机大战小游戏制作

    python版本:3.8.5 所需模块:pygame random os pygame版本:20.1 开发环境:pycharm专业版 硬件环境:win11 8G内存以上 使用python的第三方库–pygame 制作飞机大战小游戏 小游戏的内容包括: 玩家player的移动 子弹的发射 陨石的随机掉落(包括旋转 大小 下落角度) 玩家 子弹 陨石的碰撞交互

    2024年02月04日
    浏览(43)
  • 回忆童年游戏,完美利用Python制作飞机大战(爷青回~)

    名字:阿玥的小东东 学习:python、C/C++ 博客链接:阿玥的小东东的博客_CSDN博客-pythonc++高级知识,过年必备,C/C++知识讲解领域博主 目录 pygame包的安装 添加python环境变量 创建飞机大战窗口 飞机照片

    2024年02月08日
    浏览(29)
  • Unity简单操作:InputSystem获取WASD键盘输入 移动人物

      目录 安装InputSystem  在编辑的脚本中使用 InputSystem生成的脚本 Unity版本:2019.2.3f1 菜单栏/Window/Package Manager/Input System  工程面板内 右键--创建Input Actions   选中New Controls改名为PlayerControls 然后属性 面板按下Edit asset  Action Maps添加:PlayerMovement   Actions添加:New action 改名为

    2024年02月16日
    浏览(26)
  • javascript打飞机程序8x8x飞机大战js打飞机程序,飞机大战知识点包含了JavaScript面向过程的全部知识点,包括变量、运算符、判断、循环、数组、自定义函数、系统函数、事件等。...

    讲解了JavaScript编程语言制作游戏界面,添加游戏控制、制作元素动画、制作多元素场景,添加碰撞功能、制作精灵动画等功能 源码如下: html:

    2024年02月16日
    浏览(50)
  • unity制作简单的植物大战僵尸

    简单制作植物大战僵尸游戏。 协程实现各种相机动画 卡片填充方式修改为:“已填充”,实现植物恢复 事件系统实现拖拽植物 植物子弹实现对象池 这段代码是一个Unity游戏中的太阳类(Sun),实现了天上掉落的太阳落下的功能。具体实现如下: isSkySun:bool 类型的变量,用

    2024年02月05日
    浏览(34)
  • 我的第一个NPM包:panghu-planebattle-esm(胖虎飞机大战)使用说明

    好家伙,我的包终于开发完啦   欢迎使用胖虎的飞机大战包!! 为你的主页添加色彩 这是一个有趣的网页小游戏包,使用canvas和js开发 使用ES6模块化开发 效果图如下:  (觉得图片太sb的可以自己改) 代码已开源!! Git: https://gitee.com/tang-and-han-dynasties/panghu-planebattle-esm.git NPM: panghu-pla

    2023年04月19日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包