2019年7月22日 学习日记

我的游戏开发笔记(五):Animator的运用二 好了好了,上篇说到如何用代码来控制Animator里的条件参数,话不多说,直接开始。 Animator m_Animator;m_Animator = GetComponent(); m_Animator.SetBool("OnGround", true); 很简单地几行代码就可以给参数赋值了,通过查API我们可以知道SetBool的第一个参数是Animator的参数名字,第二个参数 阅读详情

说实话今天是二十三号,不过我在补二十二号的博客,现在已经是晚上了,今天也发生了很多有趣的事情比如遇到了打伞也没有用的雨,倔强的我就算全身湿透也不愿放弃外出欣赏风景的机会,于是我买了一身新衣服加人字拖,松花江畔独自小酌。享受孤独和美好的景色也是生活的一部分。

让我们来进行一个回忆,这个过程可能和我第一天的日记有一些重叠,不过不要在意,因为这是我从第一个游戏又做到第六个游戏了,刚开始我直接做第六个游戏,出现了一系列问题,我就决定先打一下基础,了解一下这个软件的逻辑结构和代码使用方式。
1、挂上角色和场景
2、创建一个组件并将角色挂在上面
3、在组件上挂上rigidbody和collider
4、创建C#脚本控制角色
5、由于这个游戏存在AI(人工智能——敌人),且和玩家角色的 很多行为都一样,这里我们选择利用C#中的继承,将玩家和敌人的共同点都放在一个公共的Character上,这会减少代码量让代码显得有层次感。
6、创建我们需要的变量和需要实例化的接口:

    protected CharacterController cc;//这里是cc控件
    protected Animator animator;//动画控件
    protected bool rotateComplete = true;//旋转是否完成(转身)
    Vector3 pendingVelocity;//向量——》速度
    public float runSpeed;//跑动速度
    public float jumpPower;//跳跃瞬间给速
    public int damage = 100;//一次攻击的伤害
    public int health = 100;//生命值
    public GameObject deathFX;//死亡特效,需要用GameObject点出来

取到控件:

 private void Awake()
    {
        cc = GetComponent<CharacterController>();//得到当前CharacterController脚本
        animator = GetComponentInChildren<Animator>();//得到角色下的Animator,子节点下的animator(model)
    }

由于我们将Character脚本挂在了Character控件上而不是Player,且Player是Character的子节点,这时候要想得到子节点的脚本就需要用GetComponentInChildren方法。

刷新方法,这个是比较重要的,因为每一帧都要检测,且大部分方法都要在这里进行调用以对游戏产生实时的影响:

    private void Update()
    {
        //移动
        pendingVelocity.z = 0f;//z轴速度锁定
        cc.Move(pendingVelocity * Time.deltaTime);//移动方向为速度乘以前后帧差时间 
        //更新动画
        animator.SetFloat("Speed", cc.velocity.magnitude);//magnitude返回了向量的长度,即距离(0,0,0)。最常用来返回物体的移动速度,这个只能读取,也可以用标准化后除以速度
        animator.SetBool("Grounded", cc.isGrounded);//methodname,bool
        //更新重力
        pendingVelocity.y += cc.isGrounded ? 0f : Physics.gravity.y * 10f * Time.deltaTime;//在地上就没有y速度,没在地上就要受到重力作用,单位i力*g*时间帧差
        AttackCheck();
    }

这里其实有一个小问题,就是pendingVelocity的值在哪里取到
更新动画的方法就是对animator中设置的过程判断量进行传入,对其值进行更新。
更新重力是为了让物体飞起来的时候有一个竖直向下大小-10m/s^2的加速度,判断条件就是在不在地上
至于最后的攻击检测,就是看这个角色有没有被攻击,不管是人或者是敌人都有被攻击的可能。
下面对各个模块进行说明:

    public void Jump()
    {
        if (cc.isGrounded)//在地上
        {
            pendingVelocity.y = jumpPower;//跳跃后初始速度
        }
    }

很简单的跳跃方法,先利用自带的charactercontroller组件中的isGrounded方法得到物体是否在地上,再巨顶是否进行y轴速度的改变(跳跃)


    public void Move(float inputX)//移动函数
    {
        pendingVelocity.x = inputX * runSpeed;//x轴速度大小为,单位方向乘以运动的速度runSpeed
    }

移动函数,其实和跳跃函数差不多,本质就是对物体速度对应轴速度的改变,不过这里有方向和速度,两部分分开给,明显这里的inputX是要用我们的getAxis方法来得到,而runspeed则需要我们来自己设置,来确定速度的大小。


    public void Rotate(Vector3 lookDir, float turnSpeed)//转向速度
    {
        rotateComplete = false;//旋转未完成
                               //   var targetPos = transform.position + lookDir;//目标位置是原位置加上方向向量后的位置
        var characterPos = transform.position;//取到现在的位置
        //去掉y轴影响
        //characterPos.y = 0;
        //   targetPos.y = 0;
        //角色面朝的向量
        //   Vector3 faceToDir = targetPos - characterPos;//目标向量减去原向量,也就是LookDir
        Vector3 faceToDir = lookDir;
        //角色面朝目标方向的四元数
        Quaternion faceToQuat = Quaternion.LookRotation(faceToDir);
        //球面插值
        Quaternion slerp = Quaternion.Slerp(transform.rotation, faceToQuat, turnSpeed * Time.deltaTime);
        if (slerp == faceToQuat)
        {
            rotateComplete = true;
        }
        transform.rotation = slerp;
    }

这个比较复杂,我决定先看一遍代码明天早上再复习一遍然后写这个解析
2019年7月24日 09:03:40
我们在上面声明的bool变量在这里派上了用场,用来判断旋转是否完成。刚开始赋值。其实这个变量本质上只在这个旋转方法里面用,在外部并不会影响什么,因此初值对结果没有影响。其中取消y影响的代码已经被我注释了,因为对物体的运动感不影响,我不知道这段代码的作用,也不知道自己是不是以后会知道,先标出来。这里他用两个向量的插值来确定面向的方向,而实际上在二维空间内,横方向只有正负一,因此我们可以直接把接收来的lookDIr来用于面向方向的判断,不需要进行减法直接进行赋值。——>下面用到了一个库(方法),四元数库。我们通过角色要面向的方向可以通过Quaternion.LookRotation方法来得到一个四元数类型的字段,我们需要通过这个四元数字段来当作形参来调用Slerp方法。:Quaternion.Slerp(transform.rotation, faceToQuat, turnSpeed * Time.deltaTime);这里的理解方法是从transform.rotation旋转到faceToQuat(四元数)这个角度,且旋转速度为每一帧以turnSpeed进行转动,一旦我们新创建的四元数和我们通过面向方向得到的四元数相等了,旋转就完成了,transform.rotation也就变成了slerp(四元数)


死亡函数:

    public void Death()
    {
        var fx = Instantiate(deathFX, transform.position, Quaternion.Euler(Vector3.zero));
        Destroy(fx, 2);
        Destroy(gameObject);
    }

Instantiate是用来复制东西的,在官方API中Quaternion.Euler:Returns a rotation that rotates z degrees around the z axis, x degrees around the x axis, and y degrees around the y axis.意思是绕指定轴旋转指定度数。而instantiate是复制一个deathFX物体并旋转Vector3.zero角度后放在Transform.position位置。//加载物体5秒后销毁游戏物体 Destroy (gameObject, 5);可见我们在两秒之后摧毁对应游戏组件再摧毁玩家角色本身。特效在人消失的两秒后消失。


承受伤害函数:

public void TakeDamage(Character inflicter, int damage)
    {
        inflicter.Jump();
        health -= damage;
        if (health<=0)
        {
            Death();
        }
    }

敌人和我们都可以受到伤害,因此这个方法两方都有调用,不过这里存在同一命名空间的自调用,因此一起说明。

    public void AttackCheck()
    {
        var dist = cc.height / 2;
        //向下射线检测
        RaycastHit hit;
        if (Physics.Raycast(transform.position, Vector3.down, out hit, dist + 0.05f))
            //public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);
            
        {
            if (hit.transform.GetComponent<Character>()&&hit.transform!=transform)
            {
                hit.transform.GetComponent<Character>().TakeDamage(this, damage);
            }
        }
    }

这人受到伤害跳一下的设定真的很超级玛丽,生命值自减也无所谓,生命值缩减到零或者零之下死亡也没毛病,主要是谁来调用函数。可见,上面的先声明了一个变量来接收角色的高度,而这里要利用的就是射线,通过设置射线的长度和方向、起点,来判断我们是否踩中了敌人的头部Physics.Raycast(transform.position, Vector3.down, out hit, dist + 0.05f),取到当前角色位置,竖直向下方向,长度为dist+0.05,判断hit是否成功。
hit若能得到被hit的角色组件并击中的不是施加攻击的角色,则会给被hit角色一个伤害。即:hit.transform.GetComponent<Character>().TakeDamage(this, damage);
说实话,前面这一大串:hit.tansform.GetComponent(),其实就是一个Character,如果前面要是命名了一个变量来接收,就不用写。其中hit.transform就挂着游戏对象,因此这里的this就是对应的击中角色,damage代表掉血。


下面看AI敌人的制作方法
下面看AI敌人的制作方法
下面看AI敌人的制作方法
下面看AI敌人的制作方法
下面看AI敌人的制作方法
下面看AI敌人的制作方法
下面看AI敌人的制作方法:

    Character character;
    float lastCheckStateTime = 0;
    float simulateInputX;
    bool simulateJump;
    void Start()
    {
        character = GetComponent<Character>();
    }
    void Update()
    {
        if (Time.time > lastCheckStateTime + 2)//判断时间间隔是否超过两秒
        {
            lastCheckStateTime = Time.time;      //改变检测时间的前time秒
            simulateInputX = Random.Range(-1f, 1f);//输入的X值在正负一之间取到
            simulateJump = Random.Range(0, 2) == 1 ? true : false;//跳跃
        }
        MoveControl(simulateInputX);
        JumpControl(simulateJump);
    }

    void MoveControl(float inputX)
    {
        character.Move(inputX);
        if (inputX != 0)
        {
            var dir = Vector3.right * inputX;//转向方向为单位向量乘以接收的正负一,其实说到底也是-+1
            character.Rotate(dir, 10);
        }
    }
    void JumpControl(bool jump)
    {
        if (jump)
        {
            character.Jump();//调用跳跃方法
            simulateJump = false;//每次AI跳跃之后一定要把simulateJump给关了
        }
    }

这里是直接对方法的调用,不过是由自己随机输入来传给他的父亲命名空间。再创建一个脚本,自己写一个相机:

    public Transform target;//位置类型的目标,玩家的transform
    public float distance = 8.0f;//与目标角色的距离
    public float hight = -1.0f;//相机的高度
    private void LateUpdate()//刷新函数
    {
        if (!target)//目标未选定
        {
            return;
        }
        transform.position = target.position;//取到角色的位置
        //Z轴间隔距离
        transform.position -= Vector3.forward * distance;//在Z轴与角色有一定的距离
                                                         //transform.position =transform.position - Vector3.forward * distance;
                                                         //高度调整
        transform.position = new Vector3(transform.position.x, hight, transform.position.z);//重置高度
    }
Windows系统监控实战:Grafana+Prometheus+node_exporter保姆级配置指南(含常见问题解决) 本文提供了一份详尽的Windows系统监控实战指南,详细讲解了如何从零部署Grafana、Prometheus和node_exporter(实际为windows_exporter)监控栈。内容涵盖核心组件认知、分步配置解析、高级生产环境考量,并重点针对配置过程中常见的“No Data”问题提供了系统性的排查手册,旨在帮助用户快速搭建稳定可靠的系统资源监控平台。 阅读详情

相关推荐

Gazebo仿真UUV水下机器人:从环境搭建到避障算法实战

本文详细介绍了使用Gazebo仿真平台进行UUV水下机器人开发的全流程,涵盖从环境搭建、uuv_simulator配置、传感器集成到核心避障算法实战。通过搭建水下仿真实验室并实现基于激光雷达数据的反应式避障算法,为水下机器人算法验证与开发提供了高效、低成本的解决方案。

weixin_28840591的博客 263

7月22日日记

      我终于说了,在三天之后。我们有一个多月没有“明目张胆”的生气了。我说,我觉得,你的同学们对你的需要要比我对你的需要要大得多。我想了好久才想到这么把它说出来。其实我是想说,你知不知道,我非常的需要你,可是。。。。。。。。我不想对这三天做什么评述。我知道她看出了问题有些不对,但是她却坚决的选择了逃避。我了解她的选择,但是感情岂能是用逃避来选择的呢?随便做点什么都会比逃避要好,不是吗?   

洋葱的涂鸦板 1177

望获实时Linux与国产芯片协同:打造LinuxCNC数控机床的全栈国产化方案

本文探讨了如何通过望获实时Linux与飞腾、龙芯等国产芯片的深度协同,为LinuxCNC数控机床打造全栈国产化方案。望获实时Linux通过中断隔离等核心技术,提供亚微秒级确定性响应,解决了传统Linux系统实时性不足的痛点,使LinuxCNC得以稳定驱动高精度机床。该方案实现了从硬件、操作系统到应用软件的全栈自主可控,为工业控制领域提供了高性能、可定制的国产化选择。

weixin_29291069的博客 647

2019年7月22日学习总结

进行的暑假训练的第一天,白天主要是按部就班的学习算法竞赛进阶那本书,主要学习了位运算和递归两方面的知识。 对于位运算,书上讲了很多关于原码,反码,补码的东西,因为上学期导论学过点皮毛,所以又看了一下。 位运算知识点总结及做题应用的技巧: 1. 位运算的优先级别(上网查资料) 2. 判断奇数还是偶数 使用&运算,与1进行&,如果为1,那么该数为奇...

wcxyky的博客 368

有限元缺陷:剪切锁死

有限元缺陷:剪切锁死

wsxww11的博客 5185

CAN基础知识

CAN基础知识

shouchen1的博客 9144

irrlicht 游戏编程 有用的数学之faceTarget 旋转角色朝向目标

作用:旋转角色朝向目标。 比如玩家靠近怪物。。怪物还没有朝向玩家,怪物发现了玩家,怪物转身朝向玩家并追赶。 以前用小画家画的草图。 模拟怪物旋转Y轴朝向角色 下面用irrlicht引擎做代码演示。 //朝向目标.只旋转y轴 core::vector3df faceTarget(IAnimatedMeshSceneNode* playerNode,irr::core...

smwhotjay的专栏 377

遥感生态指数(RSEI)——四个指数的计算

遥感生态指数是在4个生态指数的基础上通过主成分变换得出的一个评价生态环境质量的指标。因此,第二部分就是要分别计算出这4个指数的值。 ①首先,是绿度指数的计算,一般用归一化植被指数(NDVI) NDVI=(NIR-Red)/(NIR+Red) 在Bandmath工具中输入NDVI计算公式 (float(b4-b3))/(b4+b3) 其中,b3、b4分别是红波段和近红外波段 ②其次,是湿度计算。 WET = c1B1 + c2B2 + c3B3...

qq_41978498的博客 9万+

animation unity 速度_Unity中物体运动速度控制动画播放速率方法

该楼层疑似违规已被系统折叠隐藏此楼查看此楼1.创建一个gameObject并添加rigibody2.在动画组件上挂载AniSpeed脚本脚本为:using System.Collections;using System.Collections.Generic;using UnityEngine;public class AniSpeed : MonoBehaviour {public float...

weixin_30930625的博客 1591

大数据领域数据采集的人工智能辅助技术

在大数据时代,“数据是石油”的隐喻早已深入人心,但采集高质量数据的过程却像“在大海里捞针”——数据源分散如繁星、格式杂乱如碎片、质量参差不齐如泥沙,传统采集方法(写死的脚本、固定的ETL流程)早已力不从心。这篇文章将带你走进AI辅助数据采集的世界:我们会用“智能捕鱼船”的比喻拆解AI如何解决传统采集的痛点,深入解析“数据源自动发现”“自适应数据解析”“实时质量管控”等核心技术的原理,用代码示例还原AI采集的真实流程,最后探讨多模态采集、联邦学习等未来趋势。

小程序开发 2354

图解ADAS电源系统架构:看懂这张图,搞懂前装摄像头的供电秘密!

别以为ADAS系统就是“摄像头 + SoC”,其实最难搞的是供电系统,尤其是要满足车规级ASIL-D安全等级时。供电时序、电压稳定性、电源监控、冗余通信链路,一个都不能少。😤一旦电源选型不对,轻则系统卡顿,重则全车失控,不是闹着玩的。

weixin_43199439的博客 671

2019年7月24日 学习日记

上一次(22日的学习日记中)我们最后提到了AI的制作,其实利用了时间的推移并把动作数据化按照参数传入方法,其中也不乏随机数。当然也有死亡时候特效的体现,复习了Instantiate方法的调用 ...

小学生高某的博客 375

Qt C++ 信号发生器控制软件

waveformComboBox->addItems({"正弦波", "方波", "三角波", "锯齿波", "脉冲波"});frequencyLabel = new QLabel("频率 (Hz):");amplitudeLabel = new QLabel("幅值 (V):");offsetLabel = new QLabel("直流偏移 (V):");} else if (currentWaveform == "三角波") {} else if (currentWaveform == "方波") {

寒寒豆豆软件公司的博客 123

7月22日的冥想和做事日记

更新版本号(06点45分2024年7月22日):积累素材1.0.3,八部金刚功1.1.2,太极1.0.3,八段锦1.1.0,横跨拉伸(一档10min)1.0.9,(自己明天开始第二档)预防自我毁灭1.0.2,背部拉伸1.0.5.冥想1.5.6,扎马步1.0.7,

小镇做题家 650

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

2018年7月22日训练日记

今天的主要任务是补昨天牛客网多校第二场的题目。 补了一道复杂二分和随机数hash+二维树状数组 然后看了rand和srand函数的资料 做了一道简单的线段树区间合并题目 晚上打了小白月赛,怎么这么难。。。不过第一次用分块打表。。。爽,J题被卡了输入,真是气死 针对本次小白月赛,我本人出现了严重的问题:读题问题。 由于这次比赛出题人故意卡题意,导致我J题上来交了很多发WA。但是之后题面更...

LSD20164388的博客 365

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

四升五日记35篇

好的,没问题!这里是35篇为陕西省商洛市商州区即将升入五年级的小学生量身打造的暑假日记,融入了商洛的地域特色、旅游和游玩元素,每篇字数在150-250字之间,日期覆盖7月20日至8月30日。---**7月20日 星期日 晴****暑假开始啦!** 终于放暑假了!感觉像小鸟飞出笼子一样自由!早上睡了个小懒觉,真舒服。下午,爸爸说带我去丹江公园转转。公园里好热闹啊,老爷爷老奶奶在打太极、下棋,小朋友们在滑梯和秋千上玩得不亦乐乎。我沿着河边的步道跑了好久,风吹在脸上凉凉的,能看到远处青青的山。丹江的水不算特别清,

499

2018年7月22日暑假训练日记

  早上补了一下昨天的j题和g题,看j题的离散处理+树状数组一顿操作感觉他就是在卡这个样例,但是好多人都这样过的,后来安逸凡告诉我居然今天更新样例了,那个算法过不去了,感觉自己白看了好久,后来又发现一个树状数组+hash优化能过的,看懂之后感觉还有些欣慰,但是还是看不懂g题,不知道他这一顿操作二分的啥。   下午看了一下这周做的题目,复习了新学的几种题型,插值,行列式,LGV和树形dp。...

m0_37772713的博客 200

7月22日学习日记

无

qq_65659076的博客 126

【嵌入式学习日记】2016年7月22日

当为[ d ]则是目彔,例如上表档名为『.gconf』的那一行; 当为[ - ]则是档案,例如上表档名为『install.log』那一行; 若是[ l ]则表示为连结档(link file); 若是[ b ]则表示为装置文件里面的可供储存的接口讴备(可随机存取装置); 若是[ c ]则表示为装置文件里面的串行端口讴备,例如键盘、鼠标(一次怅读取装置)。 蓝色表示目录;

qq_21005325的博客 351

2020-07-22

2020年7月22日毕业学习进度日记 从前天开始开始写论文的第二章内容了。 之前没有特别关注的畸变问题是第一个要写的内容。 今天问题: 调试树莓派摄像头的时候,突然vnc桌面失去信号,随后树莓派板上只亮红灯,act黄灯不亮了。 调试:上网搜索了应该是系统cd卡无法被树莓派读取问题,之前从来没有出现过这个异常。反思今天启动时上面gpio口上挂载了温湿度模块和摄像头,猜测可能是功率太大所以树莓派的电源烧掉了?把sd卡单独拔下来插到电脑里只显示boot:I盘,之前插进去是有两个盘符的。 处理方案:实验用的树莓派还

Coral's blog 699

【2014年7月份日常记录表(2014.7.1—7.31,31天)】

2014年7月份日常记录表(2014.7.1—7.31,31天) 日期 周次 编程 日记 英语 早睡 备注 2014.7.1 周二   完成     备考 2014.7.2 周三   完成     备考 2014.7.3 周四   完成     概率论考试 2014...

weixin_33724046的博客 153

学习日记

看书计划:每月一本c++算法方向的书,一本python ML方向的书 O(∩_∩)O~~ 2019-07月 ★★★★★ 《cs231n》~() ★★★★★ 《算法竞赛进阶指南》~() ★★★☆ ☆ 《算法之美》~() ★★★☆ ☆ 《deeplearning深度学习笔记v5.1》~() 2019-06月 ★★★★★ 《算法竞赛进阶指南》~() ★★★★★ 《LeetCode提高班——第1期》~(2...

WMXNLFD的博客 359

ACM训练日记—7月22日

      感觉这个周一直在做题看题,有些题目确实有些难度,有的时候连看懂题解都会成为一种奢侈,就像牛客多校第二场的题目,G题的那个思维,对前缀和与前缀价值和的利用真的巧妙,虽然这个题是感觉能出,可那个代码的细节处理对我确实是一种挑战,另外,好不容易看懂了J题,思路大致与我当时树形dp的定义法一样,可还是那个状态转移的的方法。。。不说那套题目了,还是太菜QAQ。        这个周大致想想也就...

snayf的博客 155

学习日记2

看书计划:每月一本c++算法方向的书,一本python ML方向的书 O(∩_∩)O~~ 2019-07月 ★★★★★ 《cs231n》~() ★★★★★ 《算法竞赛进阶指南》~() ★★★☆ ☆ 《算法之美》~() ★★★☆ ☆ 《deeplearning深度学习笔记v5.1》~() ★★★☆ ☆ 《算法笔记》~() ★★★☆ ☆ 《学习OpenCV》~() ★★★☆ ☆ 《OpenCV图像处...

weixin_30505485的博客 165

【2023年7月26日记】:总结项目流程

【2023年7月26日记】:总结项目流程

嵌入式up 827
上一篇: 2019年7月21日学习日记
下一篇: 2019年7月23日 学习日记
Neepu_G.job
博客等级 码龄8年 7粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值