-------小基原创,转载请给我一个面子

网上有很多讲输入控制如何移动,但是多数都是讲单一按下,对于同时按下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做游戏常用功能实现(一)多方向同时输入也能让物体正常移动的更多相关文章

  1. 用Unity做游戏,你需要深入了解一下IL2CPP

    这次我们翻译了一篇Unity官方博客上的文章,原文题目为AN INTRODUCTION TO IL2CPP INTERNALS ,作者是从事Unity软件开发的Joshua Peterson.文章的看 ...

  2. 关于Unity实现游戏录制功能的思考

    录制无非两种做法,录制操作和录制行为. 录制操作要考虑到随机行为,但其实也可以两者混合.如果随机行为过多,并且随机行为无法用种子复现,可以完全用录制的方式 最后再统一压缩 这里yy的就是录制行为的做法 ...

  3. NSwag.AspNetCore常用功能介绍

    对于asp.net core 下的Swagger,之前一直用Swashbuckle的,因为官方推荐,再加上有老张的博客助力<从壹开始前后端分离[ .NET Core2.0/3.0 +Vue2.0 ...

  4. unity零基础开始学习做游戏(一)为了实现你的游戏,你需要提前做的准备工作

    -------小基原创,转载请给我一个面子 正所谓,工欲善其事,必现准备好电脑.接下来跟着小基一步一步来搭建你的开发环境吧 1.下载安装unity 上面的那个是破解软件,下面是unity5.5.6的安 ...

  5. unity零基础开始学习做游戏(二)让你的对象动起来

    -------小基原创,转载请给我一个面子 小基认为电子游戏与电影最重要的区别就是交互,如果电子游戏没有让你输入的交互功能的话,全程都"只可远观,而不可鼓捣"的话,你可能是在看视频 ...

  6. Unity 2D游戏开发教程之摄像头追踪功能

    Unity 2D游戏开发教程之摄像头追踪功能 上一章,我们创建了一个简单的2D游戏.此游戏中的精灵有3个状态:idle.left和right.这看起来确实很酷!但是仅有的3个状态却限制了精灵的能力,以 ...

  7. Unity MMORPG游戏优化经验分享

    https://mp.weixin.qq.com/s/thGF2WVUkIQYQDrz5DISxA 今天由Unity技术支持工程师高岩,根据实际的技术支持工作经验积累,分享如何对Unity MMORP ...

  8. 自制Unity小游戏TankHero-2D(3)开始玩起来

    自制Unity小游戏TankHero-2D(3)开始玩起来 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的.仅 ...

  9. 自制Unity小游戏TankHero-2D(1)制作主角坦克

    自制Unity小游戏TankHero-2D(1)制作主角坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...

随机推荐

  1. K-均值聚类算法(K-means)

        K-means是一种无监督的学习,将相似的对象归到同一个簇中.可以将一批数据分为K个不同的簇,并且每个簇的中心采用簇中所含样本的均值计算而成.     K-means算法的K值需要由用户指定, ...

  2. WIP完工入库及完工退回的几个重要问题

    1.必须向CST_COMP_SNAP_INTERFACE表中插入此工单所有工序的数据(也就是说同样的工单插入多条,只是工序号不一样) 标准文档: Note: If there are multiple ...

  3. Leetcode_67_Add Binary

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/40480151 Given two binary strin ...

  4. Linux的资源管理器

    说是资源管理器,其实就是使用命令来对Linux运行系统的参数的查看.下面就一起看一看怎么像在windows下查看资源管理器吧. 1.查看进程(额,自然是电脑上正在运行的进程咯) ps aux 其中a ...

  5. Server2012R2 ADFS3.0 The same client browser session has made '6' requests in the last '13'seconds

    本问题是在windows server2012R2系统ADFS3.0环境下遇到的,CRM2013部署ADFS后运行一段时间(大概有一两个月)后在IE浏览器中访问登陆界面点击登陆后就报以下错误 &quo ...

  6. Java单例模式之饿汉模式与懒汉模式

    单例模式是我们在开发软件的过程中经常用到的23中常用的java模式之一,主要的功能就是保证我们所使用的对象只有一个,这也在一方面减少了出错的可能性,增强了代码的健壮.单例模式一般来说有两种实现的方式, ...

  7. Live555 直播源 以及MediaSubsession

    /* * H264DeviceSource.hh * * Created on: 2014年7月19日 * Author: zjzhang */ #ifndef H264DEVICESOURCE_HH ...

  8. MySQL学习笔记_7_MySQL常用内置函数

    MySQL常用内置函数 说明: 1)可以用在SELECT/UPDATE/DELETE中,及where,orderby,having中 2)在函数里将字段名作为参数,变量的值就是字段所对应的每一行的值. ...

  9. 介绍几个好用的android自定义控件

    首先看效果图, 看下这两个界面,第一个中用到了一个自定义的FlowRadioGroup,支持复合子控件,自定义布局: 第二个界面中看到了输入的数字 自动4位分割了吧:也用到了自定义的DivisionE ...

  10. (十五)UITableViewCell的常见属性

    UItableViewCellStyle: typedef NS_ENUM(NSInteger, UITableViewCellStyle) { UITableViewCellStyleDefault ...