03、游戏角色创建和控制

Unity作为游戏开发引擎,具有非常强大的功能。本系列文章作为unity游戏开发的个人学习笔记,仅供参考,请勿转载。


游戏角色创建

  • 资源导入
  • 添加角色动画
  • 创建角色动画状态机
  • 编写角色控制器脚本

资源导入

资源可以先从unity自带的商店下载导入,也可以自己制作后直接拖入项目中。


打开资源商店

可以直接在搜索框中快速搜索自己想要的资源,也可以点击在浏览器打开,筛选自己需要的种类,或者可以先把资源收藏,然后在自己的收藏夹中下载导入。


使用资源商店

也可以点击自己的头像,点击我的资源选择自己以前的资源导入。


导入资源
选择自己需要的资源导入

将资源拖入指定目录


调整资源路径

在资源目录中选中对应的精灵表资源


选中要使用的精灵表

选择Sprite模式为多个,然后点击编辑,将精灵表按size切片,最后选择压缩格式为无。


编辑精灵表

添加角色动画

可以先调整自己资源图片的尺寸,修改单位像素数为适合自己项目的,然后点击应用


调整比例

选择待机动画精灵表资源,将该资源拖入场景中


拖入动画资源

在我们用来指定存放动画的路径中创建动画


创建动画

在检查器中修改对象层级


image.png

然后就可以在场景中看到拖入的角色


拖入角色动画

点击播放预览,可以看到动画效果


角色动画预览

同理,创建其他动作的动画


角色动作演示

然后在动画资源夹下删除多余的动画控制器


删除控制器

将场景中多余的动画也删除,只保留待机动画


删除多余的动作,只保留idle待机动画

将该对象以及动画控制器重命名为Player,并设置标签


重命名位Player

在检查器中将标签设置为Player

添加碰撞体组件


添加2d胶囊碰撞器

调整碰撞器大小和位置尽量接近角色

绿色椭圆代表角色的碰撞体

继续添加2D刚体组件,用来实现对角色的操控,并且锁定Z轴防止其旋转


继续添加2D刚体

禁用Z轴旋转

创建角色动画状态机

重命名Idle的动画控制器为Player


选择基础动作的动画的控制器为主要控制器

在控制器中添加若干空状态,并命名为对应的动作,并设置相应的动画


创建空状态

重命名并设置动作动画

设置完成

设置状态变量,来决定动画状态的转换


在这里添加新的状态变量参数

新建状态,用来控制对应动画的转换逻辑,更多的变量能操控更多的动画,或者用来监视角色的某些状态数值

关联不同状态来实现动画状态转换的逻辑


新建状态转化关联

点击选中该关联

在检查器中点击加号创建新的约束,speed大于0.01。表示在速度大于0.01时,角色动画会由idel转化为run

同理,创建由run转化为idel的关联

在speed小于0.01的时候,动画将会由run转化为idel

跳跃状态可由任意状态转化来

通过isGround来判定是否是跳跃状态

编写角色控制器脚本

创建新脚本


新建C#脚本,并重命名为PlayerScript

使用vs来编辑脚本


双击打开脚本编辑器(需要在安装unity时选择安装vs开发工具模块)

简单地编写一些角色的基本控制代码

代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;

public class PlayerScript : MonoBehaviour
{
    //开放参数给外部的编辑器
    [SerializeField] float maxSpeed = 10f;
    [SerializeField] float jumpSpeed = 10f;
    [SerializeField] LayerMask whatIsGround;//设置地面层
    [SerializeField] float groundRadius = 0.5f;//脚底检测半径
    [SerializeField] int maxJumpCount = 1;//落地前最多跳跃次数

    Transform groundCheck;//判断是否与地面接触的空物体
    bool grounded = false;//是否在地面上
    Animator anim;//动画控制器
    Rigidbody2D body;//角色身体
    bool facingRight = true;//角色朝向
    bool jump = false;//是否按跳跃键

    int jumpCount = 0;//当前跳跃次数

    private void Awake()
    {
        //初始化部分变量
        groundCheck = transform.Find("GroundCheck");
        anim = GetComponent<Animator>();
        body = GetComponent<Rigidbody2D>();
    }

    private void FixedUpdate()
    {
        grounded = false;
        Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheck.position, groundRadius, whatIsGround);
        foreach (Collider2D collider in colliders)
        {
            //遍历接触的面,判断是否在地面上
            if (collider.gameObject != gameObject)
            {
                grounded = true;
                jumpCount = 0;
                /*if (body.velocity.y == 0)//落地后(垂直方向速度为0),清空跳跃计数
                {
                    jumpCount = 0;
                    anim.SetInteger("jumpCount", jumpCount);
                }*/
            }
        }
        if (!grounded && jumpCount == 0)
        {
            jumpCount = 1;
        }
        //修改动画控制器变量
        anim.SetInteger("jumpCount", jumpCount);
        anim.SetBool("isGround", grounded);
        anim.SetFloat("vSpeed", body.velocity.y);

        //获取水平方向运动和跳跃操作
        float h = Input.GetAxis("Horizontal");//水平移动 1:向右;-1:向左;
        if (!jump)
        {
            jump = Input.GetButtonDown("Jump");
        }
        Move(h, jump);//移动方法
        jump = false;

        /*var t = Task.Run(async delegate
        {
            await Task.Delay(1000);
            jump = false;//每隔1s检测一次跳跃键
            if (grounded)
            {
                jumpCount = 0;
                anim.SetInteger("jumpCount", jumpCount);
            }
        });*/

    }

    void Move(float move, bool jumping)
    {
        anim.SetFloat("speed", Mathf.Abs(move));
        body.velocity = new Vector2(move * maxSpeed, body.velocity.y);//移动角色
        if ((move > 0 && !facingRight) || (move < 0 && facingRight))
        {
            //运动方向与朝向不一致时,反转朝向
            Filp();
        }

        //在地面上跳跃时,添加跳跃力
        //if (jumping && anim.GetBool("isGround"))
        if (jumping)
        {
            if (grounded)
            {
                jumpCount = 1;
                Jump();
            }
            else
            {
                if (jumpCount < maxJumpCount)
                {
                    jumpCount++;
                    Jump();
                }
            }
        }
    }

    void Jump()
    {
        grounded = false;
        anim.SetBool("isGround", false);
        anim.SetInteger("jumpCount", jumpCount);
        //body.AddForce(new Vector2(0f, jumpForce));
        body.velocity = new Vector2(body.velocity.x, jumpSpeed);//跳跃
    }


    void Filp()//反转角色朝向
    {
        facingRight = !facingRight;
        Vector3 scale = transform.localScale;
        scale.x *= -1;
        transform.localScale = scale;
    }
}

将脚本添加给角色


在检查器里点击底部添加组件按钮,搜索自己刚才添加的脚本

添加脚本

给角色添加一个空对象

给该对象重命名为GroundCheck,用来作为地面碰撞检测点

将该对象的位置移动到角色底部

在层级中选中地形Grid,然后在检查器中添加图层

新建图层TileMap

将地形设置为该图层

调整角色的参数以及脚本的参数

这时运行游戏,会发现动作不流畅,这时候需要调整动作状态的过渡


在动画控制器中选中关联箭头,去掉推出时间的勾选,调整过渡渐变,直到动作流畅

然后再运行游戏演示,可以看到操作效果


操作演示

至此,一个基本的可供操作的游戏角色便创建完成了。

©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容