一直很喜欢仙剑系列游戏,觉得仙剑的人物控制也很顺手,学习了Unity后就很想做一个类似于仙剑的人物控制方案。

又特地重玩了仙剑三,现将仙剑三的人物控制操作罗列如下:

键盘A:面向Y轴的顺时针旋转镜头,观察人物;(我这里的面向Y轴,就是指的从上向下看)

键盘D:面向Y轴的逆时针旋转镜头,观察人物;

键盘↑、↓、←、→:前后左右移动人物(需要注意的是:这里的前后左右是相对于镜头当前朝向方向的前后左右,其实就是在镜头所在的坐标轴下进行移动)

双击上述按键:跑

鼠标滚轴顺时针滚动(从鼠标右侧观察的顺时针):效果等同键盘A;

鼠标滚轴逆时针滚动(从鼠标右侧观察的逆时针):效果等同键盘D;

鼠标左键单击:地图选点人物向选点走动;

鼠标左键双击:地图选点人物向选点跑动;

我对于以上操作做了如下改动:

1.定义W/D来控制镜头向下和镜头向上转;

2.用Shitf来代替键盘双击与鼠标双击进行的跑动控制

3.代码中只考虑人物在X-Z轴平面上的移动,也就是说,人物只会绕着Y轴进行旋转

以下是两部分的代码,所有需要注意的内容都在注释中也明了。

绑定到mainCamera上的代码:

using UnityEngine;
using System.Collections;public class mainCameraForXianjian : MonoBehaviour {//游戏对象-主角色private GameObject target = null;//镜头距离主角的距离public float distance = 2.0f;//纵向最大观察角度(相当于限定了俯视的最大角度)private float maxAngleInXAxis = 80;//纵向最小观察角度(相当于限定了仰视的最大角度)private float minAngleInXAxis = -20;//横向镜头角度private float x = 0;//纵向镜头角度private float y = 0;// Use this for initializationvoid Start () {//查找主角target = GameObject.Find ("rule");if (target == null) {return;}//初始化镜头角度x = target.transform.eulerAngles.y;y = target.transform.eulerAngles.x;}// Update is called once per framevoid LateUpdate () {if (target == null) {return;}//定义:Ctrl + 鼠标滚轴 为调整镜头距主角距离(从鼠标右侧观察鼠标,滚轴顺时针拉近镜头,滚轴逆时针拉远镜头)if (Input.GetKey (KeyCode.LeftControl) || Input.GetKey (KeyCode.RightControl)) {distance -= Input.GetAxis ("Mouse ScrollWheel") * 2.0f;//从鼠标右侧观察鼠标,滚轴顺时针值为正,逆时针值为负,之所以“-=”就是想顺时针拉近镜头}//x -= Input.GetAxis ("Mouse X") * 4.0f;//y += Input.GetAxis ("Mouse Y") * 1.5f;//定义:DirectikonHorizontal为方向横向输入量,W/A/S/D分别代表镜头绕着角色看角色上面、左边、下面、右边x -= Input.GetAxis ("DirectionHorizontal");y -= Input.GetAxis ("DirectionVertical");//定义:鼠标滚轴,为从鼠标右侧观察鼠标,滚轴顺时针绕着角色观察角色左边if (!Input.GetKey (KeyCode.LeftControl) && !Input.GetKey (KeyCode.RightControl)) {x += Input.GetAxis ("Mouse ScrollWheel") * 10;}//限定纵向观察角色的视觉范围y = ClaimValue(y, maxAngleInXAxis, minAngleInXAxis);Quaternion rotation = Quaternion.Euler(new Vector3 (y, x, 0));//计算镜头最新位置Vector3 position = Quaternion.Euler (y, x, 0) * (new Vector3 (0, 0, -distance)) + target.transform.position;gameObject.transform.rotation = rotation;gameObject.transform.position = position;}float ClaimValue(float value, float maxValue, float minValue){if (value < -360) {value += 360;}if (value > 360) {value -= 360;}return Mathf.Clamp (value, minValue, maxValue);}
}

绑定在主角上的代码:

using UnityEngine;
using System.Collections;public class NewBehaviourScript : MonoBehaviour {//角色移动方向public const int HERO_UP = 0;public const int HERO_RIGHT = 1;public const int HERO_DOWN = 2;public const int HERO_LEFT = 3;public int state = 0;//角色跑动时的速度public int runSpeed = 15;//角色走动时的速度public int moveSpeed = 10;//当前角色移动速度(默认为走动)private int curSpeed = 10;//当前角色动画名称private string animState = "walk";//当前角色是否在进行鼠标点选移动private bool bMouseMove = false;//鼠标点选的目标位置private Vector3 targetPos = Vector3.zero;public void Awake(){state = HERO_UP;}// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {//定义:Shift 代表移动模式为runif (Input.GetKey (KeyCode.LeftShift) || Input.GetKey (KeyCode.RightShift)) {animState = "run";curSpeed = runSpeed;} else {animState = "walk";  curSpeed = moveSpeed;}/*******************************************************************************************//**********************************鼠标点选移动模式*******************************************///鼠标左键:角色向鼠标指向位置移动if (Input.GetMouseButton(0)) {Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);RaycastHit hit;if (Physics.Raycast (ray, out hit)) {//设置当前为鼠标点选移动模式bMouseMove = true;targetPos = new Vector3 (hit.point.x, gameObject.transform.position.y, hit.point.z);//调整角色面向目的地gameObject.transform.LookAt (targetPos);}}//在鼠标点选移动模式下,角色不停地向目的地前进if (bMouseMove) {    //播放动画gameObject.GetComponent<Animation> ().Play (animState);//如果角色临界目的地,则移动角色到目的地,并停止移动if ((Vector3.Distance (gameObject.transform.position, targetPos)) <= curSpeed * Time.deltaTime) { //Vector3.Distance(gameObject.transform.position, targetPos) < (float)curSpeedgameObject.transform.position = targetPos;bMouseMove = false;} else {//由于人物方向已经确定好了,所以以自身坐标系向目的地前进gameObject.transform.Translate (Vector3.forward * curSpeed * Time.deltaTime, Space.Self);}}/*******************************************************************************************//**********************************键盘移动模式**********************************************///定义:MoveVertical为UP/DOWN键;MoveHorizontal为RIGHT/LEFT键float KeyVertical = Input.GetAxis ("MoveVertical");float KeyHorizontal = Input.GetAxis ("MoveHorizontal");if (KeyVertical == 1) {setHeroState (HERO_DOWN);} else if (KeyVertical == -1) {setHeroState(HERO_UP);}if (KeyHorizontal == 1) {setHeroState (HERO_RIGHT);} else if (KeyHorizontal == -1) {setHeroState(HERO_LEFT);}if ((KeyVertical == 0 && KeyHorizontal == 0) && !bMouseMove) {gameObject.GetComponent<Animation>().Play ();}}//控制角色移动一次public void setHeroState(int newState){bMouseMove = false;//gameObject.transform.rotation = Quaternion.Euler(0, Camera.main.transform.eulerAngles.y, 0) ;gameObject.transform.rotation = Quaternion.Euler(0, Camera.main.transform.eulerAngles.y + (int)newState * 90, 0) ;int rotateValue = 0;Vector3 transformValue = new Vector3 ();gameObject.GetComponent<Animation> ().Play (animState);//获取当前镜头的欧拉角Vector3 newVector3 = Camera.main.transform.rotation.eulerAngles;//将欧拉角的x/z置空,因为这里只考虑角色在Y轴上的旋转newVector3.x = 0;newVector3.z = 0;//将角色旋转的欧拉角转换为四元数,以便对目标向量进行旋转Quaternion quter = Quaternion.Euler (newVector3);switch (newState) {case HERO_UP://quter乘以Vector3.forward的目的是:将角色行进方向旋转到镜头的方向transformValue = quter * Vector3.forward * Time.deltaTime;//rotateValue = 0;break;case HERO_DOWN:transformValue = quter * (-Vector3.forward) * Time.deltaTime;//rotateValue = 180;break;case HERO_LEFT:transformValue = quter * Vector3.left * Time.deltaTime;//rotateValue = 270;break;case HERO_RIGHT:transformValue = quter * (-Vector3.left) * Time.deltaTime;//rotateValue = 90;break;}/* 我当是本来想用以下这部分代码的,但是由于通过Camera.main.transform.TransformDirection得到的方向中还可能含有沿X/Z轴的旋转量还需要处理,比较麻烦* 简单来说,举个例子:如果镜头是在X轴上有个30度的旋转量,那么当控制人物向前走的时候,人物就会向前下方30°走switch (newState) {case HERO_UP://quter乘以Vector3.forward的目的是:将角色行进方向旋转到镜头的方向transformValue = Camera.main.transform.TransformDirection(Vector3.forward) *  Time.deltaTime;//rotateValue = 0;break;case HERO_DOWN:transformValue = Camera.main.transform.TransformDirection(-Vector3.forward) *  Time.deltaTime;//rotateValue = 180;break;case HERO_LEFT:transformValue = Camera.main.transform.TransformDirection(Vector3.left) *  Time.deltaTime;//rotateValue = 270;break;case HERO_RIGHT:transformValue = Camera.main.transform.TransformDirection(-Vector3.left) *  Time.deltaTime;//rotateValue = 90;break;}*///gameObject.GetComponent<Transform> ().Rotate (Vector3.up, rotateValue);//将角色在指定方向在世界坐标下位移gameObject.GetComponent<Transform> ().Translate (transformValue * curSpeed, Space.World);state = newState;}
}

Unity3D下 仙剑奇侠传三 人物移动及视角控制的尝试实现及补充相关推荐

  1. 腾讯开源手游热更新方案,Unity3D下的Lua编程

    写在前面 \\ xLua是Unity3D下Lua编程解决方案,自2016年初推广以来,已经应用于十多款腾讯自研游戏,因其良好性能.易用性.扩展性而广受好评.现在,腾讯已经将xLua开源到GitHub. ...

  2. 原声大碟 -《仙剑奇侠传三·电视原声带》[MP3]

    From: VeryCD  (用于试听,请购买正版) 唱片公司: 金牌大风 压缩码率: 320K CBR 专辑介绍: ★ 风靡十余年 超人气电玩 最强热收视 奇情浪漫武侠剧 <仙剑奇侠传> ...

  3. 仙剑奇侠传三Unity开源实现

    仙剑奇侠传三Unity开源实现 项目地址:https://github.com/JasonStein/Pal3.Unity 简介 这是一个使用C#/Unity重新实现仙剑奇侠传三以及仙剑奇侠传三外传的 ...

  4. 《仙剑奇侠传三》游戏分析

    <仙剑奇侠传三>游戏分析 本篇博客是我准备入行游戏行业的第一篇博客,希望在我成功入行之后回来阅读时,能有些不一样的感悟. 前言 仙剑奇侠传作为国产RPG中最火爆的IP之一,以仙侠为主题,描 ...

  5. 马云---下一个三十年企业家最重要的素质是什么?

    马云演讲:下一个三十年企业家最重要的素质是什么? 2016-10-25 10月20日下午,马云在清华大学EMBA课堂发表题为"企业家精神与未来"主题演讲,此时他的身份是清华大学经济 ...

  6. Unity3d 下websocket的使用

    今天介绍一下如何在Unity3D下使用WebSocket. 首先介绍一下什么是websocket,以及与socket,和http的区别与联系,然后介绍一下websocket的一些开源的项目. WebS ...

  7. Qt在Windows下的三种编程环境搭建

    未经验证,记录在此. 尊重作者,支持原创,如需转载,请附上原地址:http://blog.csdn.net/libaineu2004/article/details/17363165 从QT官网可以得 ...

  8. [css] 说下line-height三种赋值方式有何区别?

    [css] 说下line-height三种赋值方式有何区别? line-height 可以有带单位及不带单位的写法(感觉其实是两种).div{line-height: 24px;line-height ...

  9. 好久没玩laravel了,5.6玩下(三)

    好久没玩laravel了,5.6玩下(三) 好了,基础的测试通了,咱们开始增删改了 思路整理 先创建项目功能控制器 然后设置路由访问规则 然后开发项目的增删改功能 1 先创建项目的控制器 php ar ...

最新文章

  1. Excel中条件格式应用的探讨之突出显示!
  2. python csv 中文乱码_python读写csv时中文乱码问题解决办法
  3. linux下线程错误码表
  4. 【学术相关】人工智能顶会审稿现状—理想中的审稿人vs实际审稿人
  5. 模板多个列表级联_如何使用word制作模版?word怎样使用模板?
  6. linux实现访问自动挂载
  7. dreamweaver代码提示失效
  8. 解决idea使用jdbc连接数据库失败的方法(针对驱动导入失败)
  9. 百度SEOdedecms织梦采集侠V2.9采集插件
  10. IDEA设置类注解和方法注解模板(绝对可用)
  11. 三种T检验的详细区分
  12. 浅谈SEO(搜索引擎优化)
  13. C++OJ题:定义哺乳动物类Mammal和Dog类
  14. 飞机大战之一:让背景先动起来
  15. (数据科学学习手札32)Python中re模块的详细介绍
  16. HTML文件命名_没有删不掉的文件:强制终止、一键解锁,样样精通
  17. android wifi 框架图,android wifi框架
  18. 平稳/非平稳信号举例
  19. 腾讯蚂蚁字节美团后台实习面经
  20. 行业便携终端串口扩展方案

热门文章

  1. wicket学习笔记(2):简单登陆页面的创建
  2. 【SIP】Centos7搭建kamailio的SIP服务器实现网络电话
  3. 康佳android 9tv,安卓4.4抢先体验:康佳易TV最大规模系统升级
  4. WPF开发:WindowsFormsHost上浮动控件方法
  5. 使用WPF开发BLE应用
  6. JAVA_eclipse插件绘制GUI界面过程
  7. 并联串联混合的电压和电流_干货 | 聊聊电阻串并联的特点及区别
  8. sci四区和中文核心期刊哪个含金量更高
  9. java epson,JavaFX和打印到Epson打印机
  10. 计算机网络之第3章 数据链路层