关于Unity中ARPG游戏人物移动(专题十一)
ARPG:动作型角色扮演类游戏
大多数的ARPG游戏都是使用摇杆操作,以第三人称摄像机的方式来跟随主角,实际上人物只走八个方向,上,下,左,右,左上,左下,右下,右上
控制角色移动的思路
1: 在ARPG游戏中,主角人物在摇杆下控制行走;
2: 主角人物遇到障碍物(碰撞器)将不会穿越过去;
3: 摇杆控制主角人物8个方向的行走;
4: 使用CharacterController 角色控制器组件: 让你在受制于碰撞的情况下很容易的进行运动,而不用处理刚体,实际上没有刚体的物理特性。角色控制器不受力的影响,仅当你调用Move函数时才运动。它执行运动,但是受制于其他碰撞器。
本来以前都是在角色上面挂载刚体(用里面的重力)和碰撞器组件,如果碰到其他的刚体还会受力会受到一些不好的影响,用了CharacterController 就不会有这种不相关的物理力的影响了。
5: 调用角色控制器的Move函数移动角色;
6: 根据摇杆的方向旋转人物动画;
CharacterController组件
1: 属性面板属性:
Slope Limit: 角色碰撞器只能爬比这个指定角度低的斜坡:(单位是degree)
Step Offset: 上楼梯模式,小于Step Offset 的台阶,可以直接上去;
Skin Width: 两个碰撞器可以互相渗透深入皮肤宽度,一般设置成radius的10%;
Min Move Distance: 调用Move函数移动的最小移动量,如果移动距离比这个小,将不移动;
center: 相对与transform的位置角色叫胶囊体中心;
height: 胶囊体高度;
Radius: 胶囊体的半径;
2: 碰撞检测:
void OnControllerColliderHit(ControllerColliderHit hit) {},和一般的碰撞器一样。有碰撞后会调用这个接口。只会在和其他带有CharacterController组件的物体发生碰撞时才调用。
目前已知这个角色控制器的碰撞接口只有这个,如果要持续碰撞,我会加一个BoxCollider组件或者Capsule之类的碰撞器,调用三个碰撞接口
3: 重要方法:
Move(Vec3 offset): 移动的距离;
如果一个角色挂载了CharacterController组件。那么要控制这个角色的移动,其实不必改变角色节点的位置,只需对这个组件进行Move操作,角色就会跟着走。
我把这个组件理解为一个可以牵动节点的可以设置特殊移动属性的胶囊体碰撞器组件Capsule Collider
遥杆编写的基本思路与原理
1:以8个方向为例,将整个圆分为 下,右下,右,右上,上,左上, 左, 左下;
2:当我们的遥感中心点位于某一个方向的范围内,那么就属于这个方向;
3.排除一个无效的摇杆区域,在这个区域内主角不会跟着移动
4.角色移动的距离是一个标量,等于速度乘于时间,而角色移动的整个行为是一个向量,所以还要考虑方向,获得摇杆的角度得知运动方向后还要把角色到最终目的地的标量距离分解成X和Z轴方向上的距离。
根据摇杆的方向算出当前距离所对应的向量的分解的系数
5.前面都是摇杆的坐标轴解析,这里是从人物的Y轴的角度看各个欧拉角,也就是编辑器上的Transform组件的Rotation里面的Y的值对应的该主角节点的旋转方向角度,0度是角色面朝前方
实例
1.创建Unity工程项目和文件目录
2.导入人物模型资源和地图资源,以及摇杆包(79)
3.人物模型的材质球shader使用Mobile Diffuse,关联好贴图,设置模型---->Rig---->Animation Type---->Legacy---->Apply
4.在人物模型的Animation里添加跑动的动画,136-161帧是跑动的帧,Wrap Mode---->Loop---->Apply,角色配置完毕,拖进场景中
5.创建一个平面Plane,关联材质,放大10倍
6.不需要添加碰撞器,只要给主角添加CharacterController组件,调整组件的胶囊体到完全盖住主角,它有碰撞区域但是不受力的影响,千万别再加Rigidbody组件了,会使得CharacterController组件无效。
7.添加摇杆,Hedgehog Team---->Easy Touch---->Add Easy Touch For C#,Hedgehog Team---->Easy Touch---->Extension---->Adding a new joystick
8.调整摄像机的位置,到可以看见主角运动的最佳位置
9.在主角下面挂载一个脚本Person来通过摇杆控制角色移动
Person.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine; enum DIR//定义一个枚举来区分角色移动的八个方向
{
INVALID_DIR = -,
UP = ,
DOWN = ,
LEFT = ,
RIGHT = ,
RU = ,
LU = ,
LD = ,
RD = ,
} public class person : MonoBehaviour
{
float move_speed = 8.0f;//角色移动速度
CharacterController c_ctrl;//角色控制器组件 public EasyJoystick joystick;//摇杆
float[] x_set;//八个方向在X轴上的分解系数
float[] z_set;//八个方向在Z轴上的分解系数
float[] rot_set;//人物面的朝向的角度表
Vector3 camera_offset; // Use this for initialization
void Start()
{
this.c_ctrl = this.GetComponent<CharacterController>(); //按照上,下,左,右,右上,左上,左下,右下的顺序配置
this.x_set = new float[] { , , -, , 0.707f, -0.707f, -0.707f, 0.707f };//cos45=0.707,sin45=0.707
this.z_set = new float[] { , -, , , 0.707f, 0.707f, -0.707f, -0.707f };
this.rot_set = new float[] { , , -, , , -, -, }; this.camera_offset = Camera.main.transform.position - this.transform.position;//获取当前摄像机和人物的三维距离
} int get_dir(float r)
{
if (r >= -Mathf.PI && r < - * Mathf.PI / )
{ // 左的一部分
return (int)DIR.LEFT;
}
else if (r >= - * Mathf.PI / && r < - * Mathf.PI / )
{//左下
return (int)DIR.LD;
}
else if (r >= - * Mathf.PI / && r < - * Mathf.PI / )
{//下
return (int)DIR.DOWN;
}
else if (r >= - * Mathf.PI / && r < - * Mathf.PI / )
{//右下
return (int)DIR.RD;
}
else if (r >= - * Mathf.PI / && r < * Mathf.PI / )
{//右
return (int)DIR.RIGHT;
}
else if (r >= * Mathf.PI / && r < * Mathf.PI / )
{//右上
return (int)DIR.RU;
}
else if (r >= * Mathf.PI / && r < * Mathf.PI / )
{//上
return (int)DIR.UP;
}
else if (r >= * Mathf.PI / && r < * Mathf.PI / )
{//左上
return (int)DIR.LU;
}
else if (r >= * Mathf.PI / && r < * Mathf.PI / )
{//左的另一部分
return (int)DIR.LEFT;
}
return (int)DIR.INVALID_DIR;//无效的区域
} void walk_update()
{
float x = this.joystick.JoystickTouch.x;//摇杆坐标系的X坐标
float y = this.joystick.JoystickTouch.y;//摇杆坐标系的Y坐标
float len = (x * x + y * y);//不开根号是因为开销太大,而且是在Update里面,每帧都开根号受不了
if (len < (0.5f * 0.5f))//摇杆移动到这片区域是无效的
{
return;
} // 获取这个方向
float r = Mathf.Atan2(y, x); // 使用反三角函数, 获取向量的角度, [-PI, PI]
int dir = this.get_dir(r);
if (dir != (int)DIR.INVALID_DIR)
{
float s = this.move_speed * Time.deltaTime;//每一秒要移动的距离
Vector3 offset = new Vector3(s * this.x_set[dir], , s * this.z_set[dir]);//把这个距离分解到X和Z方向上
this.c_ctrl.Move(offset);//每一帧都移动 // 切换人物行走的朝向
Vector3 e_rot = this.transform.eulerAngles;
e_rot.y = this.rot_set[dir];
this.transform.eulerAngles = e_rot;
// end
}
// end
} // Update is called once per frame
void Update()
{
this.walk_update();
Camera.main.transform.position = this.transform.position + this.camera_offset;//保持人物和摄像机的距离不变
}
}
10.运行效果
关于Unity中ARPG游戏人物移动(专题十一)的更多相关文章
- 关于Unity中的道具拾取(专题六)
原理就是把道具做成触发器,触发器就是当我们有碰撞发生的时候,只会检测碰撞,而不会有任何改变物理运动状态的过程. 触发器非常适合道具拾取,因为它不会改变原本运动物体的任何物理属性,但是依然会检测碰撞,响 ...
- 开发指南专题十一:JEECG微云高速开发平台--基础用户权限
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/zhangdaiscott/article/details/26580037 开发指南专题 ...
- Unity中使用Attribute
Attribute是c#的语言特性 msdn说明如下: The Attribute class associates predefined system information or user-def ...
- 在Unity中使用UGUI修改Mesh绘制几何图形
在商店看到这样一个例子,表示很有兴趣,他们说是用UGUI做的.我想,像这种可以随便变形的图形,我第一个就想到了网格变形. 做法1: 细心的朋友应该会发现,每个UGUI可见元素,都有一个‘Canvas ...
- Unity中使用WebView
Unity中使用WebView @(设计) 需求,最近游戏中需要引入H5直播页面和更新比较频繁的赛事页面,需求包括:加密传参数.和Unity交互,在Unity框架下其实有几种方案: 内置函数Appli ...
- Unity中创建二维码
在网络上发现了一个可以把字符串转换成二维码的dll,但是我们要怎么使用他呢.不废话,直接进入主题. 用到的引用 using UnityEngine;using ZXing;using ZXing.Qr ...
- 在Unity中创建可远程加载的.unity3d包
在一个Unity项目中,发布包本身不一定要包括所有的Asset(译为资产或组件),其它的部分可以单独发布为.unity3d,再由程序从本地/远程加载执行,这部分不在本文讨论范围.虽然Unity并没有直 ...
- 【原创翻译】初识Unity中的Compute Shader
一直以来都想试着自己翻译一些东西,现在发现翻译真的很不容易,如果你直接把作者的原文按照英文的思维翻译过来,你会发现中国人读起来很是别扭,但是如果你想完全利用中国人的语言方式来翻译,又怕自己理解的不到位 ...
- 【unity shaders】:Unity中的Shader及其基本框架
shader和Material的基本关系 Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出.绘图单元可以依据这个输出来将图 ...
随机推荐
- LSTM(长短期记忆网络)及其tensorflow代码应用
本文主要包括: 一.什么是LSTM 二.LSTM的曲线拟合 三.LSTM的分类问题 四.为什么LSTM有助于消除梯度消失 一.什么是LSTM Long Short Term 网络即为LSTM,是一种 ...
- tmux使用心得
1,在终端输入tmux命令进入tmux, control+b x,关闭tmux的初始化session 2,创建自己的session,然后进行分屏
- centos7 修改同步时间
同步时间安装ntp软件 [root@node2 ~]# yum install ntp 将ntp设为开机启动 [root@node2 ~]# systemctl enable ntpd 修改启动参数, ...
- Codeforces Round #406 (Div. 1) B. Legacy 线段树建图跑最短路
B. Legacy 题目连接: http://codeforces.com/contest/786/problem/B Description Rick and his co-workers have ...
- 大数据实践:ODI 和 Twitter (二)
大数据实践:ODI和Twitter(二) 在前面的文章中,我们已经使用flume将数据从twitter抓取到Hive中,现在我们来看看ODI(Oracle Data Integrator)如何在HIV ...
- Spring boot设置文件上传大小限制
原文:https://blog.csdn.net/lizhangyong1989/article/details/78586421 Spring boot1.0版本的application.prope ...
- Linux 操作 oracle 数据库
1.Oracle监听启动命令:lsnrctl start 2. sqlplus 登录数据库 3.OS版本及Oracle版本 select banner from v$version; 4.查询该数 ...
- Unity3D光照前置知识——Rendering Paths(渲染路径)及LightMode(光照模式)译解
简述 Unity supports different Rendering Paths. You should choose which one you use depending on your g ...
- 数据库 简介 升级 SQLite 总结 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- useradd 命令的常见用法
在Linux系统中 useradd 是个很基本的命令,但是使用起来却很不直观.以至于在 Ubuntu 中居然添加了一个 adduser 命令来简化添加用户的操作.本文主要描述笔者在学习使用 usera ...