Unity3D研究院之鼠标控制角色移动与奔跑示例
最新补充。
一般在做鼠标选择时是从摄像机向目标点发送一条射线,然后取得射线与对象相交的点来计算3D目标点。后来在开发中发现了一个问题(射线被别的对象挡住了),就是如果主角的前面有别的游戏对象挡着。此时如果使用射线的原理,鼠标选择被档的对象,这样主角就会向被当的对象的方向行走。为了解决这个问题,我放弃使用发送射线的方法,最后通过2D的方法完美的处理了这个问题。
如下图所示,我们先把主角的3D坐标换算成屏幕中的2D坐标,当鼠标在屏幕中点击的时候取得一个目标点的2D坐标,根据这2个坐标换算出主角的2D向量。
然后我们在看看代码。
//将世界坐标换算成屏幕坐标
Vector3 vpos3 = Camera.main.WorldToScreenPoint(transform.position);
Vector2 vpos2 = new Vector2 (vpos3.x,vpos3.y);
//取得鼠标点击的屏幕坐标
Vector2 input = new Vector2 (Input.mousePosition.x,Input.mousePosition.y);
//取得主角到目标点的向量
Vector2 normalied = ((vpos2 – input)).normalized;
注意normalized是格式化向量,以为vpos2 – input是计算两个向量之间的距离,格式化后才是它们的方向。格式化后向量的取值范围在 -1 到 +1 之间。
//我们忽略Y轴的向量,把2D向量应用在3D向量中。
Vecotr3 targetDirection = new Vector3(normalied.x,0.0f,normalied.y) ;
//根据照相机的角度计算真实的方向
float y = Camera.main.transform.rotation.eulerAngles.y;
targetDirection = Quaternion.Euler(0f,y – 180,0f) * targetDirection;
摄像机的角度决定着主角移动的方向,y是摄像机当前角度,180是摄像机默认的角度,摄像机在旋转的时候y是会动态改变的,所以需要 y – 180 。用Quaternion.Euler()方法计算一个rotation ,然后乘以默认的向量targetDirection就是主角在3D中真实需要移动的方向。
//最后使用角色控制器移动主角就可以
Vector3 movement = targetDirection * moveSpeed + new Vector3 (0, verticalSpeed, 0) + inAirVelocity;
CharacterController controller = GetComponent<CharacterController>();
collisionFlags = controller.Move(movement);
不知道大家理解了没有?如果没有理解就在我的博客下面留言,我回即时的解答的、OK继续忙碌拉。
详细代码示例请看这篇文章. Unity3D研究院之处理摄像机跟随避免相机穿墙拉近的方法(四十四)
———————————————————–华丽的分割线—————————————-
看到这个标题我相信大家应该并不陌生,一般在PC网络游戏中玩家通过鼠标左键在游戏世界中选择角色目标移动位置,接着主角将面朝点击的那个方向移动。首先就本文来说我们应当掌握的知识点是“鼠标拣选”。这是什么概念呢?其实很简单,就是玩家通过鼠标在Game视图中选择了一个点,需要得到该点在3D世界中的三维坐标系。Game视图是一个2D的平面,所以鼠标拣选的难点就是如何把一个2D坐标换算成3D坐标。我们可以使用射线的原理很好的解决这个问题,在平面中选择一个点后从摄像机向该点发射一条射线。判断:选择的这个点是否为地面,如果是地面拿到这个点的3D坐标即可。如下图所示,在场景视图中我们简单的制作了带坡度的地形,目标是用户点击带坡度或不带坡度的地形都可以顺利的到达目的地。
在Project视图中鼠标右键选择Import Package ->Script引入官方提供的脚本,这些脚本主要是应用于摄像机朝向的部分。首先在Hierarchy视图中选择摄像机组件,接着在导航栏菜单中选择Compont -> Camera-Control ->SmoothFollow脚本。实际意义是将跟随脚本绑定在摄像机之上,目的是主角移动后摄像机也能跟随主角一并移动。如下图所示,脚本绑定完毕后可在右侧监测面板视图中看到Smooth Follow脚本。Target 就是射向摄像机朝向的参照物,这里把主角对象挂了上去意思是摄像机永远跟随主角移动。
01
|
// The target we are following
|
02
|
var target : Transform;
|
03
|
// The distance in the x-z plane to the target
|
04
|
var distance = 10.0;
|
05
|
// the height we want the camera to be above the target
|
06
|
var height = 5.0;
|
07
|
// How much we
|
08
|
var heightDamping = 2.0;
|
09
|
var rotationDamping = 3.0;
|
10
|
11
|
// Place the script in the Camera-Control group in the component menu
|
12
|
@script AddComponentMenu( "Camera-Control/Smooth Follow" )
|
13
|
14
|
function LateUpdate () {
|
15
|
// Early out if we don't have a target
|
16
|
if (!target)
|
17
|
return ;
|
18
|
19
|
// Calculate the current rotation angles
|
20
|
var wantedRotationAngle = target.eulerAngles.y;
|
21
|
var wantedHeight = target.position.y + height;
|
22
|
23
|
var currentRotationAngle = transform.eulerAngles.y;
|
24
|
var currentHeight = transform.position.y;
|
25
|
26
|
// Damp the rotation around the y-axis
|
27
|
currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
|
28
|
29
|
// Damp the height
|
30
|
currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
|
31
|
32
|
// Convert the angle into a rotation
|
33
|
34
|
//下面是原始代码。
|
35
|
//var currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
|
36
|
37
|
//这里是我修改的,直接让它等于1,
|
38
|
//摄像机就不会旋转。
|
39
|
var currentRotation = 1;
|
40
|
41
|
// Set the position of the camera on the x-z plane to:
|
42
|
// distance meters behind the target
|
43
|
transform.position = target.position;
|
44
|
transform.position -= currentRotation * Vector3.forward * distance;
|
45
|
46
|
// Set the height of the camera
|
47
|
transform.position.y = currentHeight;
|
48
|
49
|
// Always look at the target
|
50
|
transform.LookAt (target);
|
51
|
}
|
001
|
using UnityEngine;
|
002
|
using System.Collections;
|
003
|
004
|
public class Controller : MonoBehaviour
|
005
|
{
|
006
|
007
|
//人物的三个状态 站立、行走、奔跑
|
008
|
private const int HERO_IDLE = 0;
|
009
|
private const int HERO_WALK = 1;
|
010
|
private const int HERO_RUN = 2;
|
011
|
012
|
//记录当前人物的状态
|
013
|
private int gameState = 0;
|
014
|
015
|
//记录鼠标点击的3D坐标点
|
016
|
private Vector3 point;
|
017
|
private float time;
|
018
|
019
|
void Start ()
|
020
|
{
|
021
|
//初始设置人物为站立状态
|
022
|
SetGameState(HERO_IDLE);
|
023
|
024
|
}
|
025
|
026
|
void Update ()
|
027
|
{
|
028
|
//按下鼠标左键后
|
029
|
if (Input.GetMouseButtonDown(0))
|
030
|
{
|
031
|
//从摄像机的原点向鼠标点击的对象身上设法一条射线
|
032
|
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
033
|
RaycastHit hit;
|
034
|
//当射线彭转到对象时
|
035
|
if (Physics.Raycast(ray, out hit))
|
036
|
{
|
037
|
//目前场景中只有地形
|
038
|
//其实应当在判断一下当前射线碰撞到的对象是否为地形。
|
039
|
040
|
//得到在3D世界中点击的坐标
|
041
|
point = hit.point;
|
042
|
043
|
//设置主角面朝这个点,主角的X 与 Z轴不应当发生旋转,
|
044
|
//注解1
|
045
|
transform.LookAt( new Vector3(point.x,transform.position.y,point.z));
|
046
|
047
|
//用户是否连续点击按钮
|
048
|
if (Time.realtimeSinceStartup - time <=0.2f)
|
049
|
{
|
050
|
//连续点击 进入奔跑状态
|
051
|
SetGameState(HERO_RUN);
|
052
|
} else
|
053
|
{
|
054
|
//点击一次只进入走路状态
|
055
|
SetGameState(HERO_WALK);
|
056
|
}
|
057
|
058
|
//记录本地点击鼠标的时间
|
059
|
time = Time.realtimeSinceStartup;
|
060
|
}
|
061
|
}
|
062
|
}
|
063
|
064
|
void FixedUpdate()
|
065
|
{
|
066
|
067
|
switch (gameState)
|
068
|
{
|
069
|
case HERO_IDLE:
|
070
|
071
|
break ;
|
072
|
case HERO_WALK:
|
073
|
//移动主角 一次移动长度为0.05
|
074
|
Move(0.05f);
|
075
|
break ;
|
076
|
077
|
case HERO_RUN:
|
078
|
//奔跑时移动的长度为0.1
|
079
|
Move(0.1f);
|
080
|
break ;
|
081
|
}
|
082
|
083
|
}
|
084
|
085
|
void SetGameState( int state)
|
086
|
{
|
087
|
switch (state)
|
088
|
{
|
089
|
case HERO_IDLE:
|
090
|
//播放站立动画
|
091
|
point = transform.position;
|
092
|
animation.Play( "idle" );
|
093
|
break ;
|
094
|
case HERO_WALK:
|
095
|
//播放行走动画
|
096
|
animation.Play( "walk" );
|
097
|
break ;
|
098
|
case HERO_RUN:
|
099
|
//播放奔跑动画
|
100
|
animation.Play( "run" );
|
101
|
break ;
|
102
|
}
|
103
|
gameState = state;
|
104
|
}
|
105
|
106
|
void Move( float speed)
|
107
|
{
|
108
|
109
|
//注解2
|
110
|
//主角没到达目标点时,一直向该点移动
|
111
|
if (Mathf.Abs(Vector3.Distance(point, transform.position))>=1.3f)
|
112
|
{
|
113
|
//得到角色控制器组件
|
114
|
CharacterController controller = GetComponent<CharacterController>();
|
115
|
//注解3 限制移动
|
116
|
Vector3 v = Vector3.ClampMagnitude(point - transform.position,speed);
|
117
|
//可以理解为主角行走或奔跑了一步
|
118
|
controller.Move(v);
|
119
|
} else
|
120
|
{
|
121
|
//到达目标时 继续保持站立状态。
|
122
|
SetGameState(HERO_IDLE);
|
123
|
}
|
124
|
}
|
125
|
126
|
}
|
注解1:transform.LookAt()这个方法是设定主角对象的面朝方向,这里设定的方向是鼠标选择的目标点在游戏世界中点中的3D坐标。为了避免主角X与Z轴发生旋转(特殊情况)所以我们设定朝向的Y轴永远是主角自身的Y轴。
Unity3D研究院之鼠标控制角色移动与奔跑示例相关推荐
- C语言+EasyX 鼠标控制角色移动
昨天的角色移动是键盘控制角色,今天做了改进,用鼠标控制角色移动 #include<graphics.h> #include<stdio.h> #include<conio ...
- Unity3D中,鼠标控制相机视角并且跟随玩家的几种方法(第三人称)的学习整理
第一种, 按住鼠标的右键进行移动视角,同时滚轮调正视角大小. public Transform target; //相机追随目标public float xSpeed = 200; //X轴方向拖动 ...
- 【Unity3D】键盘鼠标控制视角的移动
在3D游戏里面,视角是一个很重要的因素,部分玩家对锁视角嗤之以鼻,因此视角也是游戏制作里面需要努力的方面.其实也不难,换到Unity3D里面是想办法控制摄像机的移动.下面举一个简单的例子说明在Unit ...
- 【unity3d游戏开发之基础篇】利用射线实现鼠标控制角色转向和移动(角色移动一)...
由于最近搞2D游戏, 下面的代码配合NGUI来使用 ... 将代码拖到角色身上就OK, 实现了角色转向.移动 ,想看效果的可以将代码下下来~ 用到了向量来计算角度 以及方向, 得恶补下向量知识了 ...
- C#鼠标控制控件移动的示例
//鼠标点击控件按住不放,控件跟随移动.施放则不移动 //这里的控件可以更换为其他控件. using System; using System.Collections.Generic; using S ...
- Unity3D游戏开发第三人称角色控制的模式
众所周知,在Unity3D游戏开发中,经常会用到角色控制,一般情况下角色控制有第一人称和第三人称两种,在 RPG 游戏中通常以第三人称的形式出现.而对于第三人称角色控制而言,通常有 2 种模式,我们今 ...
- Unity3d实现鼠标控制相机绕物体旋转(带阻尼)
Unity3d实现鼠标控制相机绕物体旋转(带阻尼) 本来想的是用四元数实现球性插值实现阻尼效果,但是不知道四元数怎么绕定点旋转.因此用速度衰减的方法进行实现. 1.实现鼠标控制相机带阻尼旋转 2.实现 ...
- unity3d 摄像机跟随鼠标和键盘的控制
鼠标控制: using UnityEngine; using System.Collections; public class shubiao : MonoBehaviour { //public T ...
- Unity3D游戏编程-鼠标打飞碟
Unity3D游戏编程-鼠标打飞碟 文章目录 Unity3D游戏编程-鼠标打飞碟 一.作业要求 二.项目配置 三.项目演示 视频演示 项目下载 文字说明 项目截图 四.前置内容 MVC模式 动作管理器 ...
最新文章
- [WorldWind学习]17.视域调度(视域体裁剪)
- 项目十大管理及5大过程组概览
- 删文97篇!前UCLA教授竟是民科?不看好量子通信被禁言
- 好心酸!三星可折叠屏手机Galaxy Fold下月也无法发货
- 中国特威兹勒行业市场供需与战略研究报告
- centos6.9终端命令
- jsp中的session和上下文
- 宠物医院app开发的功能有哪些?
- 使用onvif协议操作设备
- 【AVR单片机】【Microchip Studio】01项目创建
- 批处理删除文件文件夹相关指令
- html的富文本有什么用,html中怎样使用富文本
- 手机端上传照片实现 压缩、拖放、缩放、裁剪、合成拼图等功能
- 计算机图形学算法总结
- 压力变送器和差压变送器的区别
- 绕过安卓的唯一机会,可能是利用EMUI中沉睡的AI藏宝图
- 《黄帝内经》的理论体系
- 解决阿里云存在未支付订单请支付或作废后再下单
- 项目数据字典数据导入导出
- [Oracle] 几本重要的电子图书下载