个unity中想实现以第一人称unity3d建筑漫游游怎么弄

Unity3d中场景漫游的制作
Unity3d中场景漫游的制作,非常方便!!!
首先在3d软件中准备好模型,我找了个maya制作的房子。注意:我这里用的是真实世界的比例,旁边测量工具测量的是1000cm,10米高.
新建一个unity项目:勾选你将来要用到的引擎自带的几个资源包例如:
Character Controller.unityPackage(这个里面有一个第一人称控制,一个第三人称控制。)
Particles.unityPackage
Skyboxes.unityPackage天空盒
Terrain Assets.unityPackage地形素材包
或者先新建一个空的项目,再open打开Program Files\Unity\Editor\Standard
Packages目录下的这些. unityPackage文件,效果是一样的。
真的很方便,unity把很多东西都给你预备好了,快来试试吧!!!
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。强大的BIM一键室内漫游—Walk-Through-3D
强大的BIM一键室内漫游—Walk-Through-3D
强大的BIM一键室内漫游—Walk-Through-3DWalk-Through-3D是基于Unity引擎做的第一人称视角漫游应用、可以有沉浸式的建筑物室内漫游感受。1、从revit带材质导出Unity漫游应用;2、还有天气的变化;3、无需Revit 或者是 Unity安装下的三维可视化展示;4、支持HTC Vive VR的头盔和控制器(有视频);5、支持 Intel RealSense的相机操作(有视频);01安装插件什么的就不说了,下载方式我都打包在最后了。安装完成后就可以开始操作了,revit软件中的“附加模块”可以找到下图:点击-选好位置-导出导出位置找到一个.EXE的文件---运行就可以了进入页面的设置,什么大小啊,图片质量啊,这个都自己设置吧。等待进入---文件大小不一进入进度不一样按键“O”可以调出选项进行设置,方向键的“↑↓←→”调整视角。可以设置阳光的位置、时间、声音等等可以设置下雨、下雪、多云的天气存在问题:1、材质依旧是Revit插件的软肋,支持了一部分,但支持的并不完全。2、色彩偏黄、偏暗不够明亮。优点:1、基于一款免费的插件这个漫游功能还是不错、非常的强大,你只是需要点一点就可以一键导出,而且这个导出exe直接可以运行,不用再重复的安装软件了,好歹Revit和Unity都是不小呢。2、官网上说支持HTC的VR设备以及英特尔的相机,具体怎么实现鉴于设备没有而去实操,官方给出了视频可以参考看看。3、还是忽悠忽悠领导、做完的模型做个展示啊是个不错的选择。哈哈~~~Revit插件以Walk-Through-3D全套的教程视频下载地址我都打包好了,回复“BIM漫游”就可以获取下载地址。BIM树洞做一个静谧的树洞君用建筑的语言描述IT事物;用IT的思维解决建筑问题;共建BIM桥梁,聚合团队。本学习分享资料不得用于商业用途,仅做学习交流!!如有侵权立即删除!!
本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。
百家号 最近更新:
简介: 用建筑语释IT物,以IT思谋建筑惑
作者最新文章--------------------------------------------------------------------------
昨天已经完成了场景的基本搭建,今天先简单的实现城市漫游功能,具体细节之后再进行添加
1.导入人物
在Assets文件夹下,新建一个文件夹,用于存放预制体,命名为Prefabs
打开昨天导入进去的SimplePeople资源包,打开其中的示例场景,然后我们可以进去挑选人物啦~
博主在这里选了一个画风清奇,很像程序员的一个人物&SimplePeople_BusinessMan_White&,选中,并将其拖放到Prefabs文件夹下
这样人物就准备就绪了。
2.设置场景
回到游戏场景(我命名的是&GameScene&),全选所有的地形(摄像机暂时除外),道路啊建筑啊,统一加上组件&MeshCollider&,方便与人物碰撞
3.将人物放置于场景
拖拽Prefabs文件夹里的人物到Scene视图,并为其添加CharacterController,设置属性如下
找到人物的位置,点击运行,可能会发现人物往下掉,这是因为刚才添加MeshCollider的时候,部分折叠的没有被添加上去,我们手动添加。
(报了很多错误,不过以前没有出现,并且错误暂时不影响游戏运行,最近会找一下原因所在,大家也可以在评论区指点一下,人多力量大^_^)
这时候人物就不会掉下去了,但是我们会发现,没有办法控制人物的移动,这就需要添加脚本进行控制了。
4.控制人物移动
在Scripts文件夹下,新建一个C#脚本,命名为&CharacterControl.cs&,代码如下
1 using UnityE
2 using System.C
4 public class CharacterControl : MonoBehaviour
//控制速度
public float moveSpeed = 10.0f;
public float rotateSpeed = 1.0f;
public float jumpSpeed = 4.0f;
//跳跃速度
public float gravity = 1;
//重力拉扯
private bool isMainPlayer = false;
private Animator personA
private CharacterC
public bool isJ
private bool isM
private CollisionF
private Vector3 moveD
// Use this for initialization
void Start()
if (this.gameObject.tag == "Player")
isMainPlayer = true;
cc = this.GetComponent&CharacterController&();
personAnimator = gameObject.GetComponent&Animator&();
// Update is called once per frame
void Update()
//如果当前脚本的对象是游戏者
if (isMainPlayer)
//控制移动或旋转
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
h *= Time.deltaTime * moveS
v *= Time.deltaTime * moveS
transform.Translate(h, 0, v);
transform.Rotate(0, h * rotateSpeed, 0);
//FIX THIS BUG:无法后退,因为还没有设置后退的动画
if (Mathf.Abs(Input.GetAxis("Vertical")) & 0.1f)
personAnimator.SetFloat("Speed_f", moveSpeed);
personAnimator.SetFloat("Speed_f", 0);
//按下空格跳跃
//两种跳跃情况:原地跳和一边跑一边跳(脑补出表情包...)
if (Input.GetKeyDown(KeyCode.Space) && !isJump)
personAnimator.SetBool("Jump_b", true);
isJump = true;
moveDirection = transform.TransformDirection(moveDirection);
moveDirection.y = jumpS
else if (Input.GetKeyUp(KeyCode.Space))
personAnimator.SetBool("Jump_b", false);
//if (isJump)
//模拟重力
moveDirection.y -= gravity * Time.deltaT
flags = cc.Move(moveDirection * Time.deltaTime);
//when hit the ground
if (flags == CollisionFlags.Below)
isJump = false;
接下来把脚本赋给人物,需要注意的就是,这段代码是根据Tag去判断是否为游戏者的(因为后期可能会添加一些自由移动的NPC),所以需要把人物的Tag设置为Player。
进入游戏,发现人物可以移动了,不过摄像机还不会跟随人物移动。
5.设置摄像机跟随
unity5.x的摄像机脚本与4有不同之处,所以我们先选一种简单的方法。
首先将Hierarchy中_Scene下的摄像机拖动到人物下。
设置摄像机属性如图
现在就可以漫游了。接下来就是控制动画的播放以及其他的细节处理了。
阅读(...) 评论()unity第一人称探索解谜游戏模板源码First Person Exploration,Unity3D,游戏源码,6m5m游戏素材
请求处理中...
unity第一人称探索解谜游戏模板源码First Person Exploration Kit v1.1Requires Unity 4.6.3 or& higher.Fully Compatible with Unity 5, uses Unity's UI Canvas System&First Person Exploration Kit is a complete package for creating a First Person Environmental Exploration game.It includes everything you need to get started.&Includes 6 Base ob ject types for a variety of interesting ways to interact with the worldIncludes 6 example complex and custom prefab interactable ob jectsIncludes 5 Photoshop templates included with multiple examples of graphical UI themesOver 40 interaction sound effects included!Over a dozen demo models with Photoshop texture source files included8 reticle styles includedFully documented setup and customization guide for all aspects of the packageDemo scene includedCompletely customizable
或 30 积分 ()
下载14浏览人数650交付方式直接下载
注意:【1】本站只是个免费分享平台,并不敢保证所有源码人人都能编译,因素太多,旨在学习研究,如果您有顾虑或斤斤计较就请不要下载了,大家都不容易,互相理解,才能让更多的好资源出现!【2】本站资源仅限于学习研究,请在下载后24小时内删除,不要用于任何商业用途。【3】部分素材压缩包因体积过大而上传到百度等网盘上,如果发现在本站下载的压缩包只要有几K大小,说明该压缩包里只是网盘的下载链接,并非文件损坏,本站的所有素材都是经过了审核,大家可放心下载,欢迎监督反馈。【4】做个好平台真心不容易,我们一直在努力,因本站素材量大,难免会出现某网盘下载链接失效等问题,请大家及时反馈,我们会及时修正保证您可以拿到素材,请大家支持和理解!
免责声明:本网所展示的素材与服务信息由买卖双方自行提供,其真实性、准确性和合法性由信息发布人负责。本网不提供任何保证,并不承担任何法律责任,如有不妥之处请及时反馈,本网将会妥善处理。
友情提醒:本站旨在游戏开发的学习,所分享的素材资源均来源于网络,仅适用于学习参考,尊重版权,禁止用于任何商业用途,否则后果自负,所展示的素材版权归原作者或公司所有,如果本站素材侵犯了您的权益,请联系我们,我们将及时处理。
猜您喜欢的游戏素材
0金币 / 份
1金币 / 个
1金币 / 个
0金币 / 个
1金币 / 个
0金币 / 个
0金币 / 个
2金币 / 个
0金币 / 个
1金币 / 个
好评率100%
发布素材15程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Unity3D研究院之第一人称第三人称角色控制组件修改C#版本(二十九)
Unity3D研究院之第一人称第三人称角色控制组件修改C#版本(二十九)
围观49377次
编辑日期: 字体:
之前MOMO在 文章中向大家介绍了角色控制器组件。默认系统提供了JavaScript脚本的支持,可是我们还是喜欢用C#来编写脚本,本篇文章MOMO将把角色控制器的所有脚本全部改成C#语言。方便自己也方便大家学习,哇咔咔。首先,我们将角色控制器包引入工程中。如下图所示,默认提供的脚本除了MouseLook以外其它的都是JS脚本,本篇文章MOMO将把它们全部修改成C#。刚好也是答应Unity圣典的站长录制游戏开发视频,视频中我说下一节我将教大家怎么把角色控制器组件的脚本全部改成C#。
首先把CharacterMotor.js修改成C# 它主要设置角色控制的系数,如运动、跳跃、移动、滑动等。第一人称与第三人称主角模型的移动与旋转的角度都最后都是在这里计算的,请大家好好看看这个类, 尤其是UpdateFunction()方法。
CharacterMotor.cs
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
using UnityEngine;using System.Collections;&/** *&&@Author :
*/&[RequireComponent(typeof(CharacterController))][AddComponentMenu("Character/Character Motor")]&public class CharacterMotor : MonoBehaviour {&// Does this script currently respond to input?public bool canControl&&= true;&public bool useFixedUpdate = true;&// For the next variables, @System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view.// Very handy for organization!&// The current global direction we want the character to move in.[System.NonSerialized]public Vector3 inputMoveDirection = Vector3.zero;&// Is the jump button held down? We use this interface instead of checking// for the jump button directly so this script can also be used by AIs.[System.NonSerialized]public bool inputJump&&= false;&[System.Serializable]public class CharacterMotorMovement{& // The maximum horizontal speed when moving public float maxForwardSpeed = 10.0f; public float maxSidewaysSpeed = 10.0f; public float maxBackwardsSpeed = 10.0f;& // Curve for multiplying speed based on slope (negative = downwards) public AnimationCurve slopeSpeedMultiplier = new AnimationCurve(new Keyframe(-90, 1), new Keyframe(0, 1), new Keyframe(90, 0));& // How fast does the character change speeds?&&Higher is faster. public float maxGroundAcceleration = 30.0f; public float maxAirAcceleration = 20.0f;& // The gravity for the character public float gravity = 10.0f; public float maxFallSpeed = 20.0f;& // For the next variables, @System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view. // Very handy for organization!& // The last collision flags returned from controller.Move [System.NonSerialized] public CollisionFlags collisionFlags; & // We will keep track of the character's current velocity, [System.NonSerialized] public Vector3 velocity;& // This keeps track of our current velocity while we're not grounded [System.NonSerialized] public Vector3 frameVelocity = Vector3.zero;& [System.NonSerialized] public Vector3 hitPoint = Vector3.zero;& [System.NonSerialized] public Vector3 lastHitPoint = new Vector3(Mathf.Infinity, 0, 0);}&public CharacterMotorMovement movement = new CharacterMotorMovement();&public enum MovementTransferOnJump { None, // The jump is not affected by velocity of floor at all. InitTransfer, // Jump gets its initial velocity from the floor, then gradualy comes to a stop. PermaTransfer, // Jump gets its initial velocity from the floor, and keeps that velocity until landing. PermaLocked // Jump is relative to the movement of the last touched floor and will move together with that floor.}&// We will contain all the jumping related variables in one helper class for clarity. [System.Serializable]public class CharacterMotorJumping { // Can the character jump? public bool enabled = true;& // How high do we jump when pressing jump and letting go immediately public float baseHeight = 1.0f;& // We add extraHeight units (meters) on top when holding the button down longer while jumping public float extraHeight = 4.1f;& // How much does the character jump out perpendicular to the surface on walkable surfaces? // 0 means a fully vertical jump and 1 means fully perpendicular. public float perpAmount&&= 0.0f;& // How much does the character jump out perpendicular to the surface on too steep surfaces? // 0 means a fully vertical jump and 1 means fully perpendicular. public float steepPerpAmount = 0.5f;& // For the next variables, @System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view. // Very handy for organization!& // Are we jumping? (Initiated with jump button and not grounded yet) // To see if we are just in the air (initiated by jumping OR falling) see the grounded variable. [System.NonSerialized] public bool jumping = false;& [System.NonSerialized] public bool holdingJumpButton = false;& // the time we jumped at (Used to determine for how long to apply extra jump power after jumping.) [System.NonSerialized] public float lastStartTime = 0.0f;& [System.NonSerialized] public float lastButtonDownTime = -100f;& [System.NonSerialized] public Vector3 jumpDir = Vector3.up;}&public CharacterMotorJumping&&jumping = new CharacterMotorJumping();&[System.Serializable]public class CharacterMotorMovingPlatform { public bool enabled = true;& public MovementTransferOnJump movementTransfer = MovementTransferOnJump.PermaTransfer;& [System.NonSerialized] public Transform hitPlatform;& [System.NonSerialized] public Transform activePlatform;& [System.NonSerialized] public Vector3 activeLocalPoint;& [System.NonSerialized] public Vector3 activeGlobalPoint;& [System.NonSerialized] public Quaternion activeLocalRotation;& [System.NonSerialized] public Quaternion activeGlobalRotation;& [System.NonSerialized] public Matrix4x4 lastMatrix;& [System.NonSerialized] public Vector3 platformVelocity;& [System.NonSerialized] public bool newPlatform;}&public CharacterMotorMovingPlatform movingPlatform&&= new CharacterMotorMovingPlatform();&[System.Serializable]public class CharacterMotorSliding { // Does the character slide on too steep surfaces? public bool enabled = true;& // How fast does the character slide on steep surfaces? public float slidingSpeed&&= 15f;& // How much can the player control the sliding direction? // If the value is 0.5 the player can slide sideways with half the speed of the downwards sliding speed. public float sidewaysControl = 1.0f;& // How much can the player influence the sliding speed? // If the value is 0.5 the player can speed the sliding up to 150% or slow it down to 50%. public float speedControl&&= 0.4f;}&public CharacterMotorSliding sliding&&= new CharacterMotorSliding();&[System.NonSerialized]public bool grounded = true;&[System.NonSerialized]public Vector3 groundNormal = Vector3.zero;&private Vector3&&lastGroundNormal = Vector3.zero;&private Transform tr;&private CharacterController&&controller ;&void Awake () { controller = GetComponent &CharacterController&(); tr = transform;}&private void UpdateFunction () { // We copy the actual velocity into a temporary variable that we can manipulate. Vector3 velocity&&= movement.velocity;& // Update velocity based on input velocity = ApplyInputVelocityChange(velocity);& // Apply gravity and jumping force velocity = ApplyGravityAndJumping (velocity);& // Moving platform support Vector3 moveDistance&&= Vector3.zero; if (MoveWithPlatform()) {
Vector3 newGlobalPoint&&= movingPlatform.activePlatform.TransformPoint(movingPlatform.activeLocalPoint);
moveDistance = (newGlobalPoint - movingPlatform.activeGlobalPoint);
if (moveDistance != Vector3.zero)
controller.Move(moveDistance);&
// Support moving platform rotation as well:&&&&&&&&Quaternion newGlobalRotation&&= movingPlatform.activePlatform.rotation * movingPlatform.activeLocalRotation;&&&&&&&&Quaternion rotationDiff&&= newGlobalRotation * Quaternion.Inverse(movingPlatform.activeGlobalRotation);&&&&&&&&&var yRotation = rotationDiff.eulerAngles.y;&&&&&&&&if (yRotation != 0) { &&&&&&&&// Prevent rotation of the local up vector &&&&&&&&tr.Rotate(0, yRotation, 0);&&&&&&&&} }& // Save lastPosition for velocity calculation. Vector3 lastPosition&&= tr.position;& // We always want the movement to be framerate independent.&&Multiplying by Time.deltaTime does this. Vector3 currentMovementOffset = velocity * Time.deltaTime;& // Find out how much we need to push towards the ground to avoid loosing grouning // when walking down a step or over a sharp change in slope. float pushDownOffset&&= Mathf.Max(controller.stepOffset, new Vector3(currentMovementOffset.x, 0, currentMovementOffset.z).magnitude); if (grounded)
currentMovementOffset -= pushDownOffset * Vector3.up;& // Reset variables that will be set by collision function movingPlatform.hitPlatform = null; groundNormal = Vector3.zero;&&&
// Move our character! movement.collisionFlags = controller.Move (currentMovementOffset);& movement.lastHitPoint = movement.hitPoint; lastGroundNormal = groundNormal;& if (movingPlatform.enabled && movingPlatform.activePlatform != movingPlatform.hitPlatform) {
if (movingPlatform.hitPlatform != null) {
movingPlatform.activePlatform = movingPlatform.hitPlatform;
movingPlatform.lastMatrix = movingPlatform.hitPlatform.localToWorldMatrix;
movingPlatform.newPlatform = true;
} }& // Calculate the velocity based on the current and previous position.&& // This means our velocity will only be the amount the character actually moved as a result of collisions. Vector3 oldHVelocity&&= new Vector3(velocity.x, 0, velocity.z); movement.velocity = (tr.position - lastPosition) / Time.deltaTime; Vector3 newHVelocity&&= new Vector3(movement.velocity.x, 0, movement.velocity.z);& // The CharacterController can be moved in unwanted directions when colliding with things. // We want to prevent this from influencing the recorded velocity. if (oldHVelocity == Vector3.zero) {
movement.velocity = new Vector3(0, movement.velocity.y, 0); } else {
float projectedNewVelocity&&= Vector3.Dot(newHVelocity, oldHVelocity) / oldHVelocity.sqrMagnitude;
movement.velocity = oldHVelocity * Mathf.Clamp01(projectedNewVelocity) + movement.velocity.y * Vector3.up; }& if (movement.velocity.y & velocity.y - 0.001) {
if (movement.velocity.y & 0) {
// Something is forcing the CharacterController down faster than it should.
// Ignore this
movement.velocity.y = velocity.y;
// The upwards movement of the CharacterController has been blocked.
// This is treated like a ceiling collision - stop further jumping here.
jumping.holdingJumpButton = false;
} }& // We were grounded but just loosed grounding if (grounded && !IsGroundedTest()) {
grounded = false;&
// Apply inertia from platform
if (movingPlatform.enabled &&
(movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer ||
movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)
movement.frameVelocity = movingPlatform.platformVelocity;
movement.velocity += movingPlatform.platformVelocity;
SendMessage("OnFall", SendMessageOptions.DontRequireReceiver);
// We pushed the character down to ensure it would stay on the ground if there was any.
// But there wasn't so now we cancel the downwards offset to make the fall smoother.
tr.position += pushDownOffset * Vector3.up; } // We were not grounded but just landed on something else if (!grounded && IsGroundedTest()) {
grounded = true;
jumping.jumping = false;
SubtractNewPlatformVelocity();&
SendMessage("OnLand", SendMessageOptions.DontRequireReceiver); }& // Moving platforms support if (MoveWithPlatform()) {
// Use the center of the lower half sphere of the capsule as reference point.
// This works best when the character is standing on moving tilting platforms.
movingPlatform.activeGlobalPoint = tr.position + Vector3.up * (controller.center.y - controller.height*0.5f + controller.radius);
movingPlatform.activeLocalPoint = movingPlatform.activePlatform.InverseTransformPoint(movingPlatform.activeGlobalPoint);&
// Support moving platform rotation as well:&&&&&&&&movingPlatform.activeGlobalRotation = tr.rotation;&&&&&&&&movingPlatform.activeLocalRotation = Quaternion.Inverse(movingPlatform.activePlatform.rotation) * movingPlatform.activeGlobalRotation;
}}&void FixedUpdate () { if (movingPlatform.enabled) {
if (movingPlatform.activePlatform != null) {
if (!movingPlatform.newPlatform) {
Vector3 lastVelocity&&= movingPlatform.platformVelocity;&
movingPlatform.platformVelocity = (
movingPlatform.activePlatform.localToWorldMatrix.MultiplyPoint3x4(movingPlatform.activeLocalPoint)
- movingPlatform.lastMatrix.MultiplyPoint3x4(movingPlatform.activeLocalPoint)
) / Time.deltaTime;
movingPlatform.lastMatrix = movingPlatform.activePlatform.localToWorldMatrix;
movingPlatform.newPlatform = false;
movingPlatform.platformVelocity = Vector3.zero;
} }& if (useFixedUpdate)
UpdateFunction();}&void Update () { if (!useFixedUpdate)
UpdateFunction();}&private Vector3 ApplyInputVelocityChange (Vector3 velocity) {
if (!canControl)
inputMoveDirection = Vector3.zero;& // Find desired velocity Vector3 desiredVelocity; if (grounded && TooSteep()) {
// The direction we're sliding in
desiredVelocity = new Vector3(groundNormal.x, 0, groundNormal.z).normalized;
// Find the input movement direction projected onto the sliding direction
var projectedMoveDir = Vector3.Project(inputMoveDirection, desiredVelocity);
// Add the sliding direction, the spped control, and the sideways control vectors
desiredVelocity = desiredVelocity + projectedMoveDir * sliding.speedControl + (inputMoveDirection - projectedMoveDir) * sliding.sidewaysControl;
// Multiply with the sliding speed
desiredVelocity *= sliding.slidingSpeed; } else
desiredVelocity = GetDesiredHorizontalVelocity();& if (movingPlatform.enabled && movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer) {
desiredVelocity += movement.frameVelocity;
desiredVelocity.y = 0; }& if (grounded)
desiredVelocity = AdjustGroundVelocityToNormal(desiredVelocity, groundNormal); else
velocity.y = 0;& // Enforce max velocity change float maxVelocityChange&&= GetMaxAcceleration(grounded) * Time.deltaTime; Vector3 velocityChangeVector&&= (desiredVelocity - velocity); if (velocityChangeVector.sqrMagnitude & maxVelocityChange * maxVelocityChange) {
velocityChangeVector = velocityChangeVector.normalized * maxVelocityChange; } // If we're in the air and don't have control, don't apply any velocity change at all. // If we're on the ground and don't have control we do apply it - it will correspond to friction. if (grounded || canControl)
velocity += velocityChangeVector;& if (grounded) {
// When going uphill, the CharacterController will automatically move up by the needed amount.
// Not moving it upwards manually prevent risk of lifting off from the ground.
// When going downhill, DO move down manually, as gravity is not enough on steep hills.
velocity.y = Mathf.Min(velocity.y, 0); }& return velocity;}&private Vector3 ApplyGravityAndJumping (Vector3 velocity) {& if (!inputJump || !canControl) {
jumping.holdingJumpButton = false;
jumping.lastButtonDownTime = -100; }& if (inputJump && jumping.lastButtonDownTime & 0 && canControl)
jumping.lastButtonDownTime = Time.time;& if (grounded)
velocity.y = Mathf.Min(0, velocity.y) - movement.gravity * Time.deltaTime; else {
velocity.y = movement.velocity.y - movement.gravity * Time.deltaTime;&
// When jumping up we don't apply gravity for some time when the user is holding the jump button.
// This gives more control over jump height by pressing the button longer.
if (jumping.jumping && jumping.holdingJumpButton) {
// Calculate the duration that the extra jump force should have effect.
// If we're still less than that duration after the jumping time, apply the force.
if (Time.time & jumping.lastStartTime + jumping.extraHeight / CalculateJumpVerticalSpeed(jumping.baseHeight)) {
// Negate the gravity we just applied, except we push in jumpDir rather than jump upwards.
velocity += jumping.jumpDir * movement.gravity * Time.deltaTime;
// Make sure we don't fall any faster than maxFallSpeed. This gives our character a terminal velocity.
velocity.y = Mathf.Max (velocity.y, -movement.maxFallSpeed); }& if (grounded) {
// Jump only if the jump button was pressed down in the last 0.2 seconds.
// We use this check instead of checking if it's pressed down right now
// because players will often try to jump in the exact moment when hitting the ground after a jump
// and if they hit the button a fraction of a second too soon and no new jump happens as a consequence,
// it's confusing and it feels like the game is buggy.
if (jumping.enabled && canControl && (Time.time - jumping.lastButtonDownTime & 0.2)) {
grounded = false;
jumping.jumping = true;
jumping.lastStartTime = Time.time;
jumping.lastButtonDownTime = -100;
jumping.holdingJumpButton = true;&
// Calculate the jumping direction
if (TooSteep())
jumping.jumpDir = Vector3.Slerp(Vector3.up, groundNormal, jumping.steepPerpAmount);
jumping.jumpDir = Vector3.Slerp(Vector3.up, groundNormal, jumping.perpAmount);&
// Apply the jumping force to the velocity. Cancel any vertical velocity first.
velocity.y = 0;
velocity += jumping.jumpDir * CalculateJumpVerticalSpeed (jumping.baseHeight);&
// Apply inertia from platform
if (movingPlatform.enabled &&
(movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer ||
movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)
movement.frameVelocity = movingPlatform.platformVelocity;
velocity += movingPlatform.platformVelocity;
SendMessage("OnJump", SendMessageOptions.DontRequireReceiver);
jumping.holdingJumpButton = false;
} }& return velocity;}&void OnControllerColliderHit (ControllerColliderHit hit) { if (hit.normal.y & 0 && hit.normal.y & groundNormal.y && hit.moveDirection.y & 0) {
if ((hit.point - movement.lastHitPoint).sqrMagnitude & 0.001 || lastGroundNormal == Vector3.zero)
groundNormal = hit.normal;
groundNormal = lastGroundNormal;&
movingPlatform.hitPlatform = hit.collider.transform;
movement.hitPoint = hit.point;
movement.frameVelocity = Vector3.zero; }}&private IEnumerator SubtractNewPlatformVelocity () { // When landing, subtract the velocity of the new ground from the character's velocity // since movement in ground is relative to the movement of the ground. if (movingPlatform.enabled &&
(movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer ||
movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer) ) {
// If we landed on a new platform, we have to wait for two FixedUpdates
// before we know the velocity of the platform under the character
if (movingPlatform.newPlatform) {
Transform platform&&= movingPlatform.activePlatform;
yield return new WaitForFixedUpdate();
yield return new WaitForFixedUpdate();
if (grounded && platform == movingPlatform.activePlatform)
yield return 1;
movement.velocity -= movingPlatform.platformVelocity; }}&private bool MoveWithPlatform () { return (
movingPlatform.enabled
&& (grounded || movingPlatform.movementTransfer == MovementTransferOnJump.PermaLocked)
&& movingPlatform.activePlatform != null );}&private Vector3 GetDesiredHorizontalVelocity () { // Find desired velocity Vector3 desiredLocalDirection&&= tr.InverseTransformDirection(inputMoveDirection); float maxSpeed&&= MaxSpeedInDirection(desiredLocalDirection); if (grounded) {
// Modify max speed on slopes based on slope speed multiplier curve
var movementSlopeAngle = Mathf.Asin(movement.velocity.normalized.y)&&* Mathf.Rad2Deg;
maxSpeed *= movement.slopeSpeedMultiplier.Evaluate(movementSlopeAngle); } return tr.TransformDirection(desiredLocalDirection * maxSpeed);}&private Vector3 AdjustGroundVelocityToNormal (Vector3 hVelocity, Vector3 groundNormal) { Vector3 sideways&&= Vector3.Cross(Vector3.up, hVelocity); return Vector3.Cross(sideways, groundNormal).normalized * hVelocity.magnitude;}&private bool IsGroundedTest () { return (groundNormal.y & 0.01);}&float GetMaxAcceleration (bool grounded) { // Maximum acceleration on ground and in air if (grounded)
return movement.maxGroundAcceleration; else
return movement.maxAirAcceleration;}&float CalculateJumpVerticalSpeed (float targetJumpHeight) { // From the jump height and gravity we deduce the upwards speed
// for the character to reach at the apex. return Mathf.Sqrt (2 * targetJumpHeight * movement.gravity);}&bool IsJumping () { return jumping.jumping;}&bool IsSliding () { return (grounded && sliding.enabled && TooSteep());}&bool IsTouchingCeiling () { return (movement.collisionFlags & CollisionFlags.CollidedAbove) != 0;}&bool IsGrounded () { return grounded;}&bool TooSteep () { return (groundNormal.y &= Mathf.Cos(controller.slopeLimit * Mathf.Deg2Rad));}&Vector3 GetDirection () { return inputMoveDirection;}&void&&SetControllable (bool controllable) { canControl = controllable;}&// Project a direction onto elliptical quater segments based on forward, sideways, and backwards speed.// The function returns the length of the resulting vector.float MaxSpeedInDirection (Vector3 desiredMovementDirection) { if (desiredMovementDirection == Vector3.zero)
return 0; else {
float zAxisEllipseMultiplier = (desiredMovementDirection.z & 0 ? movement.maxForwardSpeed : movement.maxBackwardsSpeed) / movement.maxSidewaysSpeed;
Vector3 temp = new Vector3(desiredMovementDirection.x, 0, desiredMovementDirection.z / zAxisEllipseMultiplier).normalized;
float length = new Vector3(temp.x, 0, temp.z * zAxisEllipseMultiplier).magnitude * movement.maxSidewaysSpeed;
return length; }}&void SetVelocity (Vector3 velocity) { grounded = false; movement.velocity = velocity; movement.frameVelocity = Vector3.zero; SendMessage("OnExternalVelocity");}&// Require a character controller to be attached to the same game object&//@script RequireComponent (CharacterController)//@script AddComponentMenu ("Character/Character Motor")&}
接着把FPSInputControoler.js修改成C#语言。它用于第一人称控制角色移动,这里会监听主角按下的方向键最后传给CharacterMotor去计算模型的位置与旋转的角度。
FPSInputController.cs
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using UnityEngine;using System.Collections;&/** *&&@Author :
*/&[RequireComponent(typeof(CharacterMotor))][AddComponentMenu("Character/FPS Input Controller")]&public class FPSInputController : MonoBehaviour {&private CharacterMotor motor ;&// Use this for initializationvoid Awake () { motor = GetComponent&CharacterMotor&();}&// Update is called once per framevoid Update () { // Get the input vector from kayboard or analog stick Vector3 directionVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));& if (directionVector != Vector3.zero) {
// Get the length of the directon vector and then normalize it
// Dividing by the length is cheaper than normalizing when we already have the length anyway
var directionLength = directionVector.magnitude;
directionVector = directionVector / directionLength;&
// Make sure the length is no bigger than 1
directionLength = Mathf.Min(1, directionLength);&
// Make the input vector more sensitive towards the extremes and less sensitive in the middle
// This makes it easier to control slow speeds when using analog sticks
directionLength = directionLength * directionLength;&
// Multiply the normalized direction vector by the modified length
directionVector = directionVector * directionLength; }& // Apply the direction to the CharacterMotor motor.inputMoveDirection = transform.rotation * directionVector; motor.inputJump = Input.GetButton("Jump");}&}
MouseLook.cs因为已经是C#语言所以就不翻译了,然后是PlatFormInputController.cs 把它转成C#语言。它和FPSInputController一样会控制主角,但是它会更加精细的计算模型旋转的插值系数。
PlatformInputController.cs
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
using UnityEngine;using System.Collections;&/** *&&@Author :
*/&[RequireComponent(typeof(CharacterController))][AddComponentMenu("Character/Platform Input Controller")]public class PlatformInputController : MonoBehaviour {&public bool autoRotate = true;public float&&maxRotationSpeed = 360;&private CharacterMotor motor ;&// Use this for initializationvoid Awake () { motor = GetComponent&CharacterMotor&();}&// Update is called once per framevoid Update () { // Get the input vector from kayboard or analog stick Vector3 directionVector = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);& if (directionVector != Vector3.zero) {
// Get the length of the directon vector and then normalize it
// Dividing by the length is cheaper than normalizing when we already have the length anyway
var directionLength = directionVector.magnitude;
directionVector = directionVector / directionLength;&
// Make sure the length is no bigger than 1
directionLength = Mathf.Min(1, directionLength);&
// Make the input vector more sensitive towards the extremes and less sensitive in the middle
// This makes it easier to control slow speeds when using analog sticks
directionLength = directionLength * directionLength;&
// Multiply the normalized direction vector by the modified length
directionVector = directionVector * directionLength; }& // Rotate the input vector into camera space so up is camera's up and right is camera's right directionVector = Camera.main.transform.rotation * directionVector;& // Rotate input vector to be perpendicular to character's up vector var camToCharacterSpace = Quaternion.FromToRotation(-Camera.main.transform.forward, transform.up); directionVector = (camToCharacterSpace * directionVector);& // Apply the direction to the CharacterMotor motor.inputMoveDirection = directionVector; motor.inputJump = Input.GetButton("Jump");& // Set rotation to the move direction
if (autoRotate && directionVector.sqrMagnitude & 0.01) {
Vector3 newForward&&= ConstantSlerp(
transform.forward,
directionVector,
maxRotationSpeed * Time.deltaTime
newForward = ProjectOntoPlane(newForward, transform.up);
transform.rotation = Quaternion.LookRotation(newForward, transform.up); }}&Vector3 ProjectOntoPlane (Vector3 v, Vector3 normal) { return v - Vector3.Project(v, normal);}&Vector3 ConstantSlerp (Vector3 from, Vector3 to, float angle) { float value = Mathf.Min(1, angle / Vector3.Angle(from, to)); return Vector3.Slerp(from, to, value);}&}
接着是ThirdPersonCamera 我们把它改成C#语言。它主要控制第三人称视角时摄像机的控制。
ThirdPersonCamera.cs
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
using UnityEngine;using System.Collections;&/** *&&@Author :
*/&public class ThirdPersonCamera : MonoBehaviour {&public Transform cameraTransform;private Transform _target;&public float distance = 7.0f;&public float height = 3.0f;&public float angularSmoothLag = 0.3f;public float angularMaxSpeed = 15.0f;&public float heightSmoothLag = 0.3f;&public float snapSmoothLag = 0.2f;public float snapMaxSpeed = 720.0f;&public float clampHeadPositionScreenSpace = 0.75f;&public float lockCameraTimeout = 0.2f;&private Vector3 headOffset = Vector3.zero;private Vector3 centerOffset = Vector3.zero;&private float heightVelocity = 0.0f;private float&&angleVelocity = 0.0f;private bool snap = false;private ThirdPersonController controller;private float targetHeight = f; &void Awake (){ if(!cameraTransform && Camera.main)
cameraTransform = Camera.main.transform; if(!cameraTransform) {
Debug.Log("Please assign a camera to the ThirdPersonCamera script.");
enabled = false;
}& _target = transform; if (_target) {
controller = _target.GetComponent&ThirdPersonController&(); }& if (controller) {
CharacterController characterController&&= (CharacterController)_target.collider;
centerOffset = characterController.bounds.center - _target.position;
headOffset = centerOffset;
headOffset.y = characterController.bounds.max.y - _target.position.y; } else
Debug.Log("Please assign a target to the camera that has a ThirdPersonController script attached.");& Cut(_target, centerOffset);}&void DebugDrawStuff (){ Debug.DrawLine(_target.position, _target.position + headOffset);&}&float&&AngleDistance (float a , float b ){ a = Mathf.Repeat(a, 360); b = Mathf.Repeat(b, 360);& return Mathf.Abs(b - a);}&void&&Apply (Transform dummyTarget, Vector3 dummyCenter){ // Early out if we don't have a target if (!controller)
return;& Vector3 targetCenter = _target.position + centerOffset; Vector3 targetHead = _target.position + headOffset;&// DebugDrawStuff();& // Calculate the current & target rotation angles float originalTargetAngle = _target.eulerAngles.y; float currentAngle = cameraTransform.eulerAngles.y;& // Adjust real target angle when camera is locked float targetAngle = originalTargetAngle; & // When pressing Fire2 (alt) the camera will snap to the target direction real quick. // It will stop snapping when it reaches the target if (Input.GetButton("Fire2"))
snap = true;& if (snap) {
// We are close to the target, so we can stop snapping now!
if (AngleDistance (currentAngle, originalTargetAngle) & 3.0)
snap = false;&
currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref angleVelocity, snapSmoothLag, snapMaxSpeed); } // Normal camera motion else {&
if (controller.GetLockCameraTimer () & lockCameraTimeout)
targetAngle = currentAngle;
// Lock the camera when moving backwards!
// * It is really confusing to do 180 degree spins when turning around.
if (AngleDistance (currentAngle, targetAngle) & 160 && controller.IsMovingBackwards ())
targetAngle += 180;&
currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref angleVelocity, angularSmoothLag, angularMaxSpeed); }& // When jumping don't move camera upwards but only down! if (controller.IsJumping ()) {
// We'd be moving the camera upwards, do that only if it's really high
float newTargetHeight = targetCenter.y + height;
if (newTargetHeight & targetHeight || newTargetHeight - targetHeight & 5)
targetHeight = targetCenter.y + height; } // When walking always update the target height else {
targetHeight = targetCenter.y + height; }& // Damp the height float currentHeight = cameraTransform.position.y; currentHeight = Mathf.SmoothDamp (currentHeight, targetHeight, ref heightVelocity, heightSmoothLag);& // Convert the angle into a rotation, by which we then reposition the camera Quaternion currentRotation = Quaternion.Euler (0, currentAngle, 0);& // Set the position of the camera on the x-z plane to: // distance meters behind the target cameraTransform.position = targetCenter; cameraTransform.position += currentRotation * Vector3.back * distance;& // Set the height of the camera&&&&cameraTransform.position = new Vector3(cameraTransform.position.x,currentHeight,cameraTransform.position.z);& // Always look at the target
SetUpRotation(targetCenter, targetHead);}&void LateUpdate () { Apply (transform, Vector3.zero);}&void&&Cut (Transform dummyTarget , Vector3 dummyCenter){ float oldHeightSmooth = heightSmoothLag; float oldSnapMaxSpeed = snapMaxSpeed; float oldSnapSmooth = snapSmoothLag;& snapMaxSpeed = 10000; snapSmoothLag = 0.001f; heightSmoothLag = 0.001f;& snap = true; Apply (transform, Vector3.zero);& heightSmoothLag = oldHeightSmooth; snapMaxSpeed = oldSnapMaxSpeed; snapSmoothLag = oldSnapSmooth;}&void SetUpRotation (Vector3 centerPos,Vector3&&headPos){ // Now it's getting hairy. The devil is in the details here, the big issue is jumping of course. // * When jumping up and down we don't want to center the guy in screen space. //&&This is important to give a feel for how high you jump and avoiding large camera movements. //&&
// * At the same time we dont want him to ever go out of screen and we want all rotations to be totally smooth. // // So here is what we will do: // // 1. We first find the rotation around the y axis. Thus he is always centered on the y-axis // 2. When grounded we make him be centered // 3. When jumping we keep the camera rotation but rotate the camera to get him back into view if his head is above some threshold // 4. When landing we smoothly interpolate towards centering him on screen Vector3 cameraPos = cameraTransform.position; Vector3 offsetToCenter = centerPos - cameraPos;& // Generate base rotation only around y-axis Quaternion yRotation = Quaternion.LookRotation(new Vector3(offsetToCenter.x, 0, offsetToCenter.z));& Vector3 relativeOffset = Vector3.forward * distance + Vector3.down * height; cameraTransform.rotation = yRotation * Quaternion.LookRotation(relativeOffset);& // Calculate the projected center position and top position in world space Ray centerRay = cameraTransform.camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 1f)); Ray topRay = cameraTransform.camera.ViewportPointToRay(new Vector3(0.5f, clampHeadPositionScreenSpace, 1f));& Vector3 centerRayPos = centerRay.GetPoint(distance); Vector3 topRayPos = topRay.GetPoint(distance);& float centerToTopAngle = Vector3.Angle(centerRay.direction, topRay.direction);& float heightToAngle = centerToTopAngle / (centerRayPos.y - topRayPos.y);& float extraLookAngle = heightToAngle * (centerRayPos.y - centerPos.y); if (extraLookAngle & centerToTopAngle) {
extraLookAngle = 0; } else {
extraLookAngle = extraLookAngle - centerToTopAngle;
cameraTransform.rotation *= Quaternion.Euler(-extraLookAngle, 0, 0); }}& Vector3 GetCenterOffset () {
return centerOffset; }&}
最后一个是ThirdPersonController我们同样把它修改成C#语言,它主要更新第三人称视角控制主角时播放的各种动画,主角移动,等等。
ThirdPersonController.cs
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
using UnityEngine;using System.Collections;&/** *&&@Author :
*/&[RequireComponent(typeof(CharacterController))]&public class ThirdPersonController : MonoBehaviour {&public AnimationClip idleAnimation ;public AnimationClip walkAnimation ;public AnimationClip runAnimation ;public AnimationClip jumpPoseAnimation;&public float walkMaxAnimationSpeed&&= 0.75f;public float trotMaxAnimationSpeed&&= 1.0f;public float runMaxAnimationSpeed&&= 1.0f;public float jumpAnimationSpeed&&= 1.15f;public float landAnimationSpeed&&= 1.0f;&private Animation _animation;&enum CharacterState { Idle = 0, Walking = 1, Trotting = 2, Running = 3, Jumping = 4,}&private CharacterState _characterState;&// The speed when walkingfloat walkSpeed = 2.0f;// after trotAfterSeconds of walking we trot with trotSpeedfloat trotSpeed = 4.0f;// when pressing "Fire3" button (cmd) we start runningfloat runSpeed = 6.0f;&float inAirControlAcceleration = 3.0f;&// How high do we jump when pressing jump and letting go immediatelyfloat jumpHeight = 0.5f;&// The gravity for the characterfloat gravity = 20.0f;// The gravity in controlled descent modefloat speedSmoothing = 10.0f;float rotateSpeed = 500.0f;float trotAfterSeconds = 3.0f;&bool canJump = true;&private float jumpRepeatTime = 0.05f;private float jumpTimeout = 0.15f;private float groundedTimeout = 0.25f;&// The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around.private float lockCameraTimer = 0.0f;&// The current move direction in x-zprivate Vector3 moveDirection = Vector3.zero;// The current vertical speedprivate float verticalSpeed = 0.0f;// The current x-z move speedprivate float moveSpeed = 0.0f;&// The last collision flags returned from controller.Moveprivate CollisionFlags collisionFlags; &// Are we jumping? (Initiated with jump button and not grounded yet)private bool jumping = false;private bool jumpingReachedApex = false;&// Are we moving backwards (This locks the camera to not do a 180 degree spin)private bool movingBack = false;// Is the user pressing any keys?private bool isMoving = false;// When did the user start walking (Used for going into trot after a while)private float walkTimeStart = 0.0f;// Last time the jump button was clicked downprivate float lastJumpButtonTime = -10.0f;// Last time we performed a jumpprivate float lastJumpTime = -1.0f;&// the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)private float lastJumpStartHeight = 0.0f;&private Vector3 inAirVelocity = Vector3.zero;&private float lastGroundedTime = 0.0f;&private bool isControllable = true;&void Awake (){ moveDirection = transform.TransformDirection(Vector3.forward);& _animation = GetComponent&Animation&(); if(!_animation)
Debug.Log("The character you would like to control doesn't have animations. Moving her might look weird.");& /*public var idleAnimation : AnimationCpublic var walkAnimation : AnimationCpublic var runAnimation : AnimationCpublic var jumpPoseAnimation : AnimationC
*/ if(!idleAnimation) {
_animation = null;
Debug.Log("No idle animation found. Turning off animations."); } if(!walkAnimation) {
_animation = null;
Debug.Log("No walk animation found. Turning off animations."); } if(!runAnimation) {
_animation = null;
Debug.Log("No run animation found. Turning off animations."); } if(!jumpPoseAnimation && canJump) {
_animation = null;
Debug.Log("No jump animation found and the character has canJump enabled. Turning off animations."); }&}&void UpdateSmoothedMovementDirection (){ Transform cameraTransform = Camera.main.transform; bool grounded = IsGrounded();& // Forward vector relative to the camera along the x-z plane
Vector3 forward = cameraTransform.TransformDirection(Vector3.forward); forward.y = 0; forward = forward.normalized;& // Right vector relative to the camera // Always orthogonal to the forward vector Vector3 right = new Vector3(forward.z, 0, -forward.x);& float v = Input.GetAxisRaw("Vertical"); float h = Input.GetAxisRaw("Horizontal");& // Are we moving backwards or looking backwards if (v & -0.2f)
movingBack = true; else
movingBack = false;& bool wasMoving = isMoving; isMoving = Mathf.Abs (h) & 0.1f || Mathf.Abs (v) & 0.1f;& // Target direction relative to the camera Vector3 targetDirection = h * right + v * forward;& // Grounded controls if (grounded) {
// Lock camera for short period when transitioning moving & standing still
lockCameraTimer += Time.deltaTime;
if (isMoving != wasMoving)
lockCameraTimer = 0.0f;&
// We store speed and direction seperately,
// so that when the character stands still we still have a valid forward direction
// moveDirection is always normalized, and we only update it if there is user input.
if (targetDirection != Vector3.zero)
// If we are really slow, just snap to the target direction
if (moveSpeed & walkSpeed * 0.9f && grounded)
moveDirection = targetDirection.normalized;
// Otherwise smoothly turn towards it
moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);&
moveDirection = moveDirection.normalized;
// Smooth the speed based on the current target direction
float curSmooth = speedSmoothing * Time.deltaTime;&
// Choose target speed
//* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
float targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0f);&
_characterState = CharacterState.Idle;&
// Pick speed modifier
if (Input.GetKey (KeyCode.LeftShift) | Input.GetKey (KeyCode.RightShift))
targetSpeed *= runSpeed;
_characterState = CharacterState.Running;
else if (Time.time - trotAfterSeconds & walkTimeStart)
targetSpeed *= trotSpeed;
_characterState = CharacterState.Trotting;
targetSpeed *= walkSpeed;
_characterState = CharacterState.Walking;
moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);&
// Reset walk time start when we slow down
if (moveSpeed & walkSpeed * 0.3f)
walkTimeStart = Time.time; } // In air controls else {
// Lock camera while in air
if (jumping)
lockCameraTimer = 0.0f;&
if (isMoving)
inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration; }&}&void ApplyJumping (){ // Prevent jumping too fast after each other if (lastJumpTime + jumpRepeatTime & Time.time)
return;& if (IsGrounded()) {
// - Only when pressing the button down
// - With a timeout so you can press the button slightly before landing
if (canJump && Time.time & lastJumpButtonTime + jumpTimeout) {
verticalSpeed = CalculateJumpVerticalSpeed (jumpHeight);
SendMessage("DidJump", SendMessageOptions.DontRequireReceiver);
} }}&void ApplyGravity (){ if (isControllable) // don't move player at all if not controllable. {
// Apply gravity
bool jumpButton = Input.GetButton("Jump");&
// When we reach the apex of the jump we send out a message
if (jumping && !jumpingReachedApex && verticalSpeed &= 0.0f)
jumpingReachedApex = true;
SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
if (IsGrounded ())
verticalSpeed = 0.0f;
verticalSpeed -= gravity * Time.deltaTime; }}&float CalculateJumpVerticalSpeed (float targetJumpHeight){ // From the jump height and gravity we deduce the upwards speed
// for the character to reach at the apex. return Mathf.Sqrt(2 * targetJumpHeight * gravity);}&void&&DidJump (){ jumping = true; jumpingReachedApex = false; lastJumpTime = Time.time; lastJumpStartHeight = transform.position.y; lastJumpButtonTime = -10;& _characterState = CharacterState.Jumping;}&void&&Update() {& if (!isControllable) {
// kill all inputs if not controllable.
Input.ResetInputAxes(); }& if (Input.GetButtonDown ("Jump")) {
lastJumpButtonTime = Time.time; }& UpdateSmoothedMovementDirection();& // Apply gravity // - extra power jump modifies gravity // - controlledDescent mode modifies gravity ApplyGravity ();& // Apply jumping logic ApplyJumping ();& // Calculate actual motion Vector3 movement = moveDirection * moveSpeed + new Vector3 (0, verticalSpeed, 0) + inAirVelocity; movement *= Time.deltaTime;& // Move the controller CharacterController controller = GetComponent&CharacterController&(); collisionFlags = controller.Move(movement);& // ANIMATION sector if(_animation) {
if(_characterState == CharacterState.Jumping)
if(!jumpingReachedApex) {
_animation[jumpPoseAnimation.name].speed = jumpAnimationSpeed;
_animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(jumpPoseAnimation.name);
_animation[jumpPoseAnimation.name].speed = -landAnimationSpeed;
_animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(jumpPoseAnimation.name);
if(controller.velocity.sqrMagnitude & 0.1f) {
_animation.CrossFade(idleAnimation.name);
if(_characterState == CharacterState.Running) {
_animation[runAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, runMaxAnimationSpeed);
_animation.CrossFade(runAnimation.name);
else if(_characterState == CharacterState.Trotting) {
_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, trotMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
else if(_characterState == CharacterState.Walking) {
_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, walkMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
} } // ANIMATION sector& // Set rotation to the move direction if (IsGrounded()) {&
transform.rotation = Quaternion.LookRotation(moveDirection);& }
Vector3 xzMove = movement;
xzMove.y = 0;
if (xzMove.sqrMagnitude & 0.001f)
transform.rotation = Quaternion.LookRotation(xzMove);
} } & // We are in jump mode but just became grounded if (IsGrounded()) {
lastGroundedTime = Time.time;
inAirVelocity = Vector3.zero;
if (jumping)
jumping = false;
SendMessage("DidLand", SendMessageOptions.DontRequireReceiver);
} }}&void&&OnControllerColliderHit (ControllerColliderHit hit ){// Debug.DrawRay(hit.point, hit.normal); if (hit.moveDirection.y & 0.01f)
return;}&float GetSpeed () { return moveSpeed;}&public bool IsJumping () { return jumping;}&bool IsGrounded () { return (collisionFlags & CollisionFlags.CollidedBelow) != 0;}&Vector3 GetDirection () { return moveDirection;}&public bool IsMovingBackwards () { return movingBack;}&public float GetLockCameraTimer () { return lockCameraTimer;}&bool IsMoving (){ return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) & 0.5f;}&bool HasJumpReachedApex (){ return jumpingReachedApex;}&bool IsGroundedWithTimeout (){ return lastGroundedTime + groundedTimeout & Time.time;}&void Reset (){ gameObject.tag = "Player";}&}
最后我们用修改的脚本来控制第三人称视角主角的移动,直接上图大家仔细看看监测面板视图中的脚本绑定,这里问题不大,图片如果看不清点击即可查看大图。乖~~~
脚本终于全部翻译完毕,其实在开发中大家可以去丰富这些脚本,灵活的运用它们。感谢Unity圣典的站长专门花钱买模型让我来写教程与录制视频教程。嚯嚯 既然是买的模型 我就不提供下载了 哇咔咔。
最后MOMO祝大家学习愉快。下回写点游戏AI的东西,让游戏中的怪物在更加聪明点吧。
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!
Pingback 引用通告:
Pingback 引用通告:
Pingback 引用通告:}

我要回帖

更多关于 unity 第一人称控制器 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信