unity做游戏常用功能实现(一)多方向同时输入也能让物体正常移动
-------小基原创,转载请给我一个面子
网上有很多讲输入控制如何移动,但是多数都是讲单一按下,对于同时按下2个或2个以上按键并没有说明怎么解决,这里小基研究了一下方便大家
(如果你直接写input.GetKey去读输入,直接执行物体移动的话,判断格个方向时逻辑时,如果使用if-elseif这种的话,多按键输入时候,必定只能执行其中一个方向。
如果用if判断各个方向,那么当“上”方向和“右”方向同时按下时,物理轨迹是“右上”方向,而你单个方向速度如果都是v的话,合速度方向为√2,相当于斜着走速度会变快,这两个方式都不能接受)
所以解决思路是当按键按下时,记录状态,抬起时重置状态,根据当前所有输入的按键状态,统一处理得出一个合方向,并且对合速度处理
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class MyInput : MonoBehaviour {
//移动方向枚举
enum MoveDir
{
None, //不动
Up, //上8
Down, //下2
Left, //左4
Right, //右6
UL, //左上7
UR, //右上9
DL, //左下1
DR, //右下3
} //输入按键常量(之后走配置)
const KeyCode INPUT_UP = KeyCode.W;
const KeyCode INPUT_DOWN = KeyCode.S;
const KeyCode INPUT_LEFT = KeyCode.A;
const KeyCode INPUT_RIGHT = KeyCode.D; //默认移动方向
private MoveDir moveDir = MoveDir.None;
//按压记录
private bool isUpPress = false;
private bool isDownPress = false;
private bool isLeftPress = false;
private bool isRightPress = false; //是否可以移动
private bool canMove = true;
//右移动
private Vector3 MOVE_RIGHT = new Vector3(, , );
//上移动
private Vector3 MOVE_UP = new Vector3(, , ); //外部调控速度
public float speed = 2f;
//移动速度向量
private Vector3 move_speed_dir = Vector3.zero;
//移动距离
private Vector3 move_dis = Vector3.zero; //控制目标
public Transform target; // Use this for initialization
void Start () { } // Update is called once per frame
void Update () {
CheckInputKey();
CheckMoveDir();
} void FixedUpdate()
{
CheckMove();
} //检测输入按键
void CheckInputKey()
{
//检测单一输入
foreach (KeyCode kcode in System.Enum.GetValues(typeof(KeyCode)))
{
if (Input.GetKeyDown(kcode))
{
//Debug.Log("Single KeyCode: " + kcode);
ChangeKeyPressState(kcode, true);
} if (Input.GetKeyUp(kcode))
{
//Debug.Log("Single KeyCode: " + kcode);
ChangeKeyPressState(kcode, false);
}
}
} //记录按键的按压状态
void ChangeKeyPressState(KeyCode keyCode, bool isPress)
{
switch(keyCode)
{
case INPUT_UP:
isUpPress = isPress;
break;
case INPUT_DOWN:
isDownPress = isPress;
break;
case INPUT_LEFT:
isLeftPress = isPress;
break;
case INPUT_RIGHT:
isRightPress = isPress;
break;
}
} //确定移动方向
void CheckMoveDir()
{
//确定方向
if(isUpPress && isLeftPress)
{
moveDir = MoveDir.UL;
}
else if(isUpPress && isRightPress)
{
moveDir = MoveDir.UR;
}
else if (isDownPress && isLeftPress)
{
moveDir = MoveDir.DL;
}
else if (isDownPress && isRightPress)
{
moveDir = MoveDir.DR;
}
else if(isUpPress)
{
moveDir = MoveDir.Up;
}
else if (isDownPress)
{
moveDir = MoveDir.Down;
}
else if (isLeftPress)
{
moveDir = MoveDir.Left;
}
else if (isRightPress)
{
moveDir = MoveDir.Right;
}
else
{
moveDir = MoveDir.None;
}
} //检测是否可以移动
void CheckMove()
{
//某些情况下可能禁止移动,例如暂停,播放CG等
if(canMove && moveDir != MoveDir.None)
{
PlayerMove(target, speed);
}
} //移动
void PlayerMove(Transform target, float speed)
{
move_dis = speed * Time.deltaTime * GetSpeedDir();
target.position += move_dis;
} //速度向量
Vector3 GetSpeedDir()
{
switch(moveDir)
{
case MoveDir.Up:
move_speed_dir = MOVE_UP;
break;
case MoveDir.Down:
move_speed_dir = -MOVE_UP;
break;
case MoveDir.Left:
move_speed_dir = -MOVE_RIGHT;
break;
case MoveDir.Right:
move_speed_dir = MOVE_RIGHT;
break;
case MoveDir.UL:
move_speed_dir = MOVE_UP - MOVE_RIGHT;
break;
case MoveDir.UR:
move_speed_dir = MOVE_UP + MOVE_RIGHT;
break;
case MoveDir.DL:
move_speed_dir = -MOVE_UP - MOVE_RIGHT;
break;
case MoveDir.DR:
move_speed_dir = -MOVE_UP + MOVE_RIGHT;
break;
}
return move_speed_dir.normalized;
}
}
update()里面每帧检测CheckInputKey(),是否有按键按下或者抬起,ChangeKeyPressState()这个方法里面记下来当前有哪些按键输入。
CheckMoveDir()这个方法就是专门为了根据按下的按键的值来判断,合方向是枚举中的哪一种
CheckMove(),PlayerMove()这两个方法就是检测当前能不能移动,能移动的话就移动
GetSpeedDir()这个方法里面就是根据方向枚举,确定移动的方向向量,确定完合方向后,记得要用.normalized取单位长度,这样就能保证斜方向速度与正交方向速度相同。
-------------------另一种思路解决多按键同时按下控制移动-----------------
上面那种方法,
CheckMoveDir()判断按下按键转换方向时,只处理了一个按键按下,和两个按键同时按下,那么如果我同时按下三个按键或者四个按键时候就会出问题
下面是修改
//移动方向枚举
enum MoveDir
{
None = , //不动
Up = , //上8
Down = -, //下2
Left = , //左4
Right = -, //右6
UL = , //左上7
UR = -, //右上9
DL = , //左下1
DR = -, //右下3
}
枚举方向定义了不同的值
//确定移动方向
void CheckMoveDir()
{
moveDirValue = ;
//确定方向
if(isUpPress)
{
moveDirValue += (int)MoveDir.Up;
}
if (isDownPress)
{
moveDirValue += (int)MoveDir.Down;
}
if (isLeftPress)
{
moveDirValue += (int)MoveDir.Left;
}
if (isRightPress)
{
moveDirValue += (int)MoveDir.Right;
} target.GetComponent<Player>().TurnDir(moveDirValue);
}
这样同时按下三个按键的时候,必定有两个方向时一对相反的,那么求“合”速度时候,就可以抵消掉,如果四个方向同时按下,就相当于不动了,问题搞定!
unity做游戏常用功能实现(一)多方向同时输入也能让物体正常移动的更多相关文章
- 用Unity做游戏,你需要深入了解一下IL2CPP
这次我们翻译了一篇Unity官方博客上的文章,原文题目为AN INTRODUCTION TO IL2CPP INTERNALS ,作者是从事Unity软件开发的Joshua Peterson.文章的看 ...
- 关于Unity实现游戏录制功能的思考
录制无非两种做法,录制操作和录制行为. 录制操作要考虑到随机行为,但其实也可以两者混合.如果随机行为过多,并且随机行为无法用种子复现,可以完全用录制的方式 最后再统一压缩 这里yy的就是录制行为的做法 ...
- NSwag.AspNetCore常用功能介绍
对于asp.net core 下的Swagger,之前一直用Swashbuckle的,因为官方推荐,再加上有老张的博客助力<从壹开始前后端分离[ .NET Core2.0/3.0 +Vue2.0 ...
- unity零基础开始学习做游戏(一)为了实现你的游戏,你需要提前做的准备工作
-------小基原创,转载请给我一个面子 正所谓,工欲善其事,必现准备好电脑.接下来跟着小基一步一步来搭建你的开发环境吧 1.下载安装unity 上面的那个是破解软件,下面是unity5.5.6的安 ...
- unity零基础开始学习做游戏(二)让你的对象动起来
-------小基原创,转载请给我一个面子 小基认为电子游戏与电影最重要的区别就是交互,如果电子游戏没有让你输入的交互功能的话,全程都"只可远观,而不可鼓捣"的话,你可能是在看视频 ...
- Unity 2D游戏开发教程之摄像头追踪功能
Unity 2D游戏开发教程之摄像头追踪功能 上一章,我们创建了一个简单的2D游戏.此游戏中的精灵有3个状态:idle.left和right.这看起来确实很酷!但是仅有的3个状态却限制了精灵的能力,以 ...
- Unity MMORPG游戏优化经验分享
https://mp.weixin.qq.com/s/thGF2WVUkIQYQDrz5DISxA 今天由Unity技术支持工程师高岩,根据实际的技术支持工作经验积累,分享如何对Unity MMORP ...
- 自制Unity小游戏TankHero-2D(3)开始玩起来
自制Unity小游戏TankHero-2D(3)开始玩起来 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的.仅 ...
- 自制Unity小游戏TankHero-2D(1)制作主角坦克
自制Unity小游戏TankHero-2D(1)制作主角坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...
随机推荐
- 分布式进阶(十一) Docker 常见错误汇总
NO.1 以上添加网桥的命令在Ubuntu14.04中是不可行的.正确的命令如下: brctl addbr br0 ifconfig br0 192.168.1.188 netmask 255.255 ...
- 4.1、Libgdx的生命周期
(原文:http://www.libgdx.cn/topic/32/4-1-libgdx%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F) 一个libgdx应 ...
- R12 - Error 'Unable to process your transaction. The operating unit is either invalid or it cannot b
In this Document Symptoms Cause Solution Still Have Questions? References APPLIES TO: Orac ...
- 简单说说Android自定义view学习推荐的方式
这几天比较受关注,挺开心的,嘿嘿. 这里给大家总结一下学习自定义view的一些技巧. 以后写自定义view可能不会写博客了,但是可以开源的我会把源码丢到github上我的地址:https://git ...
- python,os操作文件,文件路径(上一级目录)
python获取文件上一级目录:取文件所在目录的上一级目录 os.path.abspath(os.path.join(os.path.dirname('settings.py'),os.path.pa ...
- git使用详解
1. Git概念 1.1. Git库中由三部分组成 Git 仓库就是那个.git 目录,其中存放的是我们所提交的文档索引内容,Git 可基于文档索引内容对其所管理的文档进行内容追踪,从而实现文档的版本 ...
- Swift基础之UITabBarController(这是在之前UITableView中直接添加的)
这些基础内容基本已经可以搭建项目框架,剩下的就是一些优化,细节和数据请求问题,慢慢更新.... 在AppDelegate中创建方法 //创建方法执行UITabBarController func cr ...
- 如何实现 集群化/Session 复制-doc(cluster-howto.html)
源文档链接: http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html 翻译日期: 2014年3月19日 翻译人员: 铁锚 感受: Tomc ...
- 四种简单的图像显著性区域特征提取方法-----AC/HC/LC/FT。
四种简单的图像显著性区域特征提取方法-----> AC/HC/LC/FT. 分类: 图像处理 2014-08-03 12:40 4088人阅读 评论(4) 收藏 举报 salient regio ...
- gdb学习(一)[第二版]
概述 gdb是GNU debugger的缩写,是编程调试工具. 功能 1.启动程序,可以按照用户自定义的要求随心所欲的运行程序. 2.可让被调试的程序在用户所指定的断点处停住 (断点可以是条件表达式) ...