本文主要是介绍Unity2d-做一个横板动作小游戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
学习视频教程 无邪:
https://space.bilibili.com/335835274/channel/detail?cid=112338
无邪 教程
画个自己的像素人物
后续是给这个人物添加动画
直接将导出的png图片拖入Unity中,创建一个2d对象
把每个导入的动作分割成单独的16*16的图片,
多选中多张图片一起拖到对象上,则可給该对象创建动画
打开动画窗口 即可看到当前对象的所有动画
在动画界面中创建 几个全局变量来控制动画切换
在脚本代码中 获取该对象的动画组件 并通过判断player的动作 方向 来设置几个全局变量的值,理论上这几个全局变量一旦切换 动画就会根据逻辑对应的切换
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerController : MonoBehaviour
{public float MoveSpeed;private Animator Myanimator;private Rigidbody2D Myrigidbody2D;// Start is called before the first frame updatevoid Start(){MoveSpeed = 5;Myanimator = GetComponent<Animator>();Myrigidbody2D = GetComponent<Rigidbody2D>();}// Update is called once per framevoid Update(){PlayerMove();CheckPlayerDirectory();}void PlayerMove(){float MoveDirH = Input.GetAxis("Horizontal");float MoveDirV = Input.GetAxis("Vertical");Vector2 vector = new Vector2(MoveDirH * MoveSpeed, MoveDirV* MoveSpeed);Myrigidbody2D.velocity = vector;//if (Input.GetKey(KeyCode.W))//{// gameObject.transform.Translate(Vector3.up * MoveSpeed * Time.deltaTime);//}//if (Input.GetKey(KeyCode.S))//{// gameObject.transform.Translate(Vector3.down * MoveSpeed * Time.deltaTime);//}//if (Input.GetKey(KeyCode.A))//{// gameObject.transform.Translate(Vector3.left * MoveSpeed * Time.deltaTime);//}//if (Input.GetKey(KeyCode.D))//{// gameObject.transform.Translate(Vector3.right * MoveSpeed * Time.deltaTime);//}}void CheckPlayerDirectory(){if (Myrigidbody2D.velocity.x < 0){Myanimator.SetBool("IsMoveLeft", true);Debug.Log("IsMoveLeft -> true");}else{Myanimator.SetBool("IsMoveLeft", false);}/**************************************************************/if (Myrigidbody2D.velocity.x > 0){Myanimator.SetBool("IsMoveRight", true);}else{Myanimator.SetBool("IsMoveRight", false);}/**************************************************************/if (Myrigidbody2D.velocity.y > 0){Myanimator.SetBool("IsMoveUp", true);}else{Myanimator.SetBool("IsMoveUp", false);}/**************************************************************/if (Myrigidbody2D.velocity.y < 0){Myanimator.SetBool("IsMoveDown", true);}else{Myanimator.SetBool("IsMoveDown", false);}/**************************************************************/if (Mathf.Abs( Myrigidbody2D.velocity.y ) < Mathf.Epsilon && Mathf.Abs(Myrigidbody2D.velocity.x) < Mathf.Epsilon){Myanimator.SetBool("IsMoveDown", true);}}
向左走和向右走 可以共享同一个动画
具体做法是判断 角色的运动方向 并在脚本里面选择是否反转角色
代码如下
transform.localRotation = Quaternion.Euler(0,180,0);
最终还是决定做个横板跳跃游戏
人物绘制如下
一个会跳跃的小至尊宝,名字叫做Hx
做一个简易场景,给Hx的脚部添加Box Collider 2d组件 使得其能站在地面上
给Hx的身体部分添加Capsule Collider 2d 使其能和其他物体产生碰撞
添加脚本控制人物移动 和 判断人物当前运动状态 切换不同的动画
代码如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class HxControl : MonoBehaviour
{public float MoveSpeed;public bool IsAdministrator;private Rigidbody2D myrigibody;private Animator myAnimator;// Start is called before the first frame updatevoid Start(){MoveSpeed = 5;myrigibody = GetComponent<Rigidbody2D>();myAnimator = GetComponent<Animator>();//IsAdministrator = false;}// Update is called once per framevoid Update(){Run();Jump();CheckAnimotion();}private void Run(){float MoveDir = Input.GetAxis("Horizontal");Vector2 vector2 = new Vector2(MoveDir*MoveSpeed,myrigibody.velocity.y);myrigibody.velocity = vector2;}private void Jump(){if (myAnimator.GetBool("IsHxJump") || myAnimator.GetBool("IsHxFly")){}else{if (Input.GetButtonDown("Jump")){Vector2 vector2 = new Vector2(myrigibody.velocity.x, MoveSpeed * 1.4f);myrigibody.velocity = vector2;}}//确认为超级管理员 则可以随便飞if (IsAdministrator){if (Input.GetButtonDown("Jump")){Vector2 vector2 = new Vector2(myrigibody.velocity.x, MoveSpeed * 1.4f);myrigibody.velocity = vector2;}}}private void CheckAnimotion(){if (Mathf.Abs(myrigibody.velocity.x) < Mathf.Epsilon && Mathf.Abs(myrigibody.velocity.y) < Mathf.Epsilon){myAnimator.SetBool("IsHxJump", false);myAnimator.SetBool("IsHxRun", false);myAnimator.SetBool("IsHxFly", false);}else{if (Mathf.Abs(myrigibody.velocity.y) > Mathf.Abs(Mathf.Epsilon)){if (myrigibody.velocity.y > Mathf.Epsilon){myAnimator.SetBool("IsHxJump", true);}if (myrigibody.velocity.y < -Mathf.Epsilon){myAnimator.SetBool("IsHxFly", true);}}else{myAnimator.SetBool("IsHxFly", false);myAnimator.SetBool("IsHxJump", false);if (myrigibody.velocity.x < -Mathf.Epsilon){myAnimator.SetBool("IsHxRun", true);transform.localRotation = Quaternion.Euler(0, 0, 0);}if (myrigibody.velocity.x > -Mathf.Epsilon){myAnimator.SetBool("IsHxRun", true);transform.localRotation = Quaternion.Euler(0, 180, 0);}}}}}
添加攻击动画
理论上来说攻击可以从任意状态触发,则动画流程图如下
攻击状态可以从any state出现,动画结束后又可以回到之前的状态
攻击动画选用Triger类型的变量触发
触发代码为
private void Acttack(){if (Input.GetButtonDown("Attack")){myAnimator.SetTrigger("IsHxAttack");Debug.Log("IsHxAttack");}}
攻击状态下添加HitBox
在Hx下新建一个空的子对象 名字叫HxAttack
在HxAttack下面 添加组件 Polygon Colloder 2d 多边形碰撞组件 取消该组件前的复选框
添加脚本:判断当攻击按键按下时 使能碰撞组件,并一定时间后禁用碰撞组件
脚本代码如下:
public int DamdgeVal;private Animator animator;private PolygonCollider2D polygonCollider;// Start is called before the first frame updatevoid Start(){animator = GameObject.FindGameObjectWithTag("Player").GetComponent<Animator>();polygonCollider = GetComponent<PolygonCollider2D>();}// Update is called once per framevoid Update(){}void Attack(){if (Input.GetKeyDown("Attack")){polygonCollider.enabled = true;StartCoroutine(DisableHitBox());}}IEnumerator DisableHitBox(){yield return new WaitForSeconds(0.6f);polygonCollider.enabled = false;}
攻击效果实现
创建一个物体,这里我创建了一截树干
给树干添加Box Collider 2d 碰撞检测框
/// <summary>/// 怪物的血量/// </summary>public int healthVal;/// <summary>/// 怪物的伤害值/// </summary>public int damageVal;/// <summary>/// /// </summary>private SpriteRenderer sr;/// <summary>/// the base Color of The Enemy/// </summary>private Color OriginColor;
脚本代码中 添加以上变量
public void Start(){sr = GetComponent<SpriteRenderer>();OriginColor = sr.color;}
获取树干的精灵组件,将原始颜色赋值给变量
public void Update(){if (healthVal <= 0){Destroy(gameObject);}}
每一帧判断自身血量,若血量归零 则摧毁这个对象
public void TaskDamage(int damage){this.healthVal -= damage;Instantiate(BloodEffect,transform.position,Quaternion.identity);FlashColor(0.3f);}void FlashColor(float conTime){sr.color = Color.red;Invoke("ResetColor", conTime);}void ResetColor(){sr.color = OriginColor;}
新增public 受到攻击的函数 供外部对象调用
受到攻击后自身生命值减少/
初始化一个外部传进来的GameObject(这是外面写好的一个粒子特效,用作掉血效果)/
自身的颜色切换成Color.Red并延时0.3s后恢复原来的颜色
而在Hx代码块内 新增攻击函数如下:
private void OnTriggerEnter2D(Collider2D other){if (other.gameObject.CompareTag("Enemy")){other.GetComponent<Enemy>().TaskDamage(DamdgeVal);}}
若Hx的攻击范围 进入了某个Collider内,则函数内进行判断 碰撞到的Collider是否属于Enemy标签的
如果属于 则调用该Enemy的TaskDamage()函数 即攻击完成;
瓦片绘制功能
在Aseprinte中绘制6432的图像,单个3232为一个基本单元
绘制两块地面并导出图像至Unity切割;
完毕后 在场景中创建TitleMap对象,则在Grid中存在TitleMap对象,打开Title Palette窗口,将切割好的模块拖进去,即可在场景中绘制
绘制完成后需要给场景里面的TitleMap对象添加碰撞体 TitleMap Collider 2d
并添加Composite Collider 2d组件,添加这个碰撞组件之后会自动带一个Rigibody组件,将Rigibody组件中BodyType设置为Static,表明
这个对象是一个静态的对象,不受重力作用;
这些设置完毕之后 开启工程,发现在该TitleMap移动的时候 Y方向上有个很小的速度 在正负变换,我是通过Y方向上速度的正负来判断人物是
在跳起来上升阶段 还是处于下落阶段,并更改不同的动画,所以这时候判断就不能直接大于零或者小于零,应该大于0.1或者小于-0.1;
地图绘制完毕后,发现角色可以爬墙,也就是在竖直的碰撞体上,只要你一直向着墙的方向移动,则不会掉下来,此时Y方向上的速度也为0,跳跃的条件我设置的是
Y方向上速度大于0.1或者小于-0.1,此时Y方向上速度为0,则可以再次跳跃,此时就达到的爬墙的效果,虽然是一个BUG 不过准备保留,用于进入一些隐藏的关卡;
绘制了初始场景的地图 如下:
计划这里为一个选择关卡的场景
左边第一位置为攀大场景,后续根据情况再添加;
在中间靠上的位置 设置了一个牛头随机移动,后续准备做成 在平台上击打一个对象,则开启牛头的移动,没有什么作用,隐藏彩蛋。
这篇关于Unity2d-做一个横板动作小游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!