今天开始做人物--会跑会跳的韩菱纱(如何制作第三人称人物控制)
2015-04-17 10:21
176 查看
一个游戏最直观的体验就是上手的游戏化身操作了,如何让游戏化身会跑会跳,甚至卖卖萌,虽然看起来基本,但确是游戏中最重要的,因为游戏化身与游戏内的其他原件交互,都是建立在人物化身的操控系统之下的,比如说,我们想与场景中的一个npc做交互,比如对话,或者购买物品,第一点,我们要跑(走)到npc面前,而想做到这个我们就需要对玩家化身做操控。u3d这一点做得非常好,甚至自己自带了一个玩家的控制系统,包括第一人称和第三人称两种模式,我们这里主要讨论第三人称,因为不是讲解系统提供的控制系统所以我们主要入正题,讲解UnityChan插件系统,为啥用它呢,因为开始我想用Character
System4来做,但用了之后发现,Character System4因为主要是针对摇杆控制器操作的,动作匹配也与摇杆的运动很契合,但实际用到电脑游戏中他的动作有时看起来就有些奇怪,所以最后选用了UnityChan插件系统,这个系统不仅包括一个比较完善的人物动作控制,还包括脸部运动的(表情系统--不过这个需要美术的支持,我这里没能实现面部表情,-具体想学习的话,某网站有一套免费的11课时的专门讲解UnityChan插件的视频教程,喜欢的可以自己看看,如果将来有条件,我会在后续Demo里加入表情系统)我们先看一下这个插件的运行效果
看下两个开发窗口
插件中使用的预制件,主要控制的人物预制件,unitychan上面捆绑了2个脚本,我们看下代码
使得人物预制件需要3个系统组件来支持,作用呢,animator是u3d全新的动画系统的控制组件,CapsuleCollider是一个包裹人物预制件的碰撞体,而最后那个是刚体系统,
代码的FixedUpdate()方法中主要是anim.SetFloat("Speed", v);这种动画控制代码那么,具体代码是怎么控制的呢,我们看下animator中载入的控制器
我们可以看到控制器默认动作未Idle,而通过迁移线与其他动作相连,而左下方提供了控制动作变化的变量,我们就是通过变量的控制来达到动作的转换的,
我们以Jump变量为例,代码中if (Input.GetButtonDown("Jump")){}也就是空格按下,这时候如果符合条件,如人物正在跑动,那么anim.SetBool("Jump", true);这样动作控制就完成了,而另外一个类FaceUpdate.cs这个类非常简单
这个遮罩,如果按照这个系统做的表情播放不出来,那么建议去注意下这个,其他的因为这个代码很好理解,也没什么可说的,如果真的就不懂,网上有一套UnityChan的11集的免费视频教程,大家可以去看看,里面包括如果用maya来建立人物都写得很详细,最后我们就看看如何利用这些代码呢?首先我们在网上下载一个人物模型
我们以韩菱纱为例,注意我们使用的模型可以没有绑定动作,但必须顶点骨骼绑定完成的,否则,我们导出的fbx文件将是石膏模,我们在场景中是无法使用的,具体怎么导出,在菜单里找导出,然后选fbx文件格式就行了,当然导其他的格式也可以,但需要注意的是,要是u3d支持的3d格式,然后我们把导好的模型复制进工程文件夹,
,记得先把贴图赋一下,之后,我们点击hls0这个fbx文件我们设置生成Avatar
具体为什么设置avatar我建议不明白的小伙伴去看这篇文章配置Avatar,然后把hls0做成预制件,具体做法就是拖到
就可以了,之后我们在属性窗口中,绑定我们需要的
里面的参数需要自己按照自己的模型来调整
关于数据我们可以按照需要自己调整,比如我们可以改变JumpPower来改变化身跳跃的高度,其实这个场景中还有一个比较重要的预制件,
就是摄像机,我们依靠这个来达到相机跟谁化身效果,但,untiychan里面的两个摄像机控制方式都跟我们平时玩的3剑游戏控制方式不同,所以在我的仙剑Demo中没有用到这个预制件,等后面我会讲解我们在Demo中用到的镜头跟随方法,最后我们看下我们最终做的人物是什么样的吧,
System4来做,但用了之后发现,Character System4因为主要是针对摇杆控制器操作的,动作匹配也与摇杆的运动很契合,但实际用到电脑游戏中他的动作有时看起来就有些奇怪,所以最后选用了UnityChan插件系统,这个系统不仅包括一个比较完善的人物动作控制,还包括脸部运动的(表情系统--不过这个需要美术的支持,我这里没能实现面部表情,-具体想学习的话,某网站有一套免费的11课时的专门讲解UnityChan插件的视频教程,喜欢的可以自己看看,如果将来有条件,我会在后续Demo里加入表情系统)我们先看一下这个插件的运行效果
看下两个开发窗口
插件中使用的预制件,主要控制的人物预制件,unitychan上面捆绑了2个脚本,我们看下代码
// // Mecanimのアニメーションデータが、原点で移動しない場合の Rigidbody付きコントローラ // サンプル // 2014/03/13 N.Kobyasahi // using UnityEngine; using System.Collections; // 必要なコンポーネントの列記 [RequireComponent(typeof (Animator))] [RequireComponent(typeof (CapsuleCollider))] [RequireComponent(typeof (Rigidbody))] public class UnityChanControlScriptWithRgidBody : MonoBehaviour { public float animSpeed = 1.5f; // アニメーション再生速度設定 public float lookSmoother = 3.0f; // a smoothing setting for camera motion public bool useCurves = true; // Mecanimでカーブ調整を使うか設定する // このスイッチが入っていないとカーブは使われない public float useCurvesHeight = 0.5f; // カーブ補正の有効高さ(地面をすり抜けやすい時には大きくする) // 以下キャラクターコントローラ用パラメタ // 前進速度 public float forwardSpeed = 7.0f; // 後退速度 public float backwardSpeed = 2.0f; // 旋回速度 public float rotateSpeed = 2.0f; // ジャンプ威力 public float jumpPower = 3.0f; // キャラクターコントローラ(カプセルコライダ)の参照 private CapsuleCollider col; private Rigidbody rb; // キャラクターコントローラ(カプセルコライダ)の移動量 private Vector3 velocity; // CapsuleColliderで設定されているコライダのHeiht、Centerの初期値を収める変数 private float orgColHight; private Vector3 orgVectColCenter; private Animator anim; // キャラにアタッチされるアニメーターへの参照 private AnimatorStateInfo currentBaseState; // base layerで使われる、アニメーターの現在の状態の参照 private GameObject cameraObject; // メインカメラへの参照 // アニメーター各ステートへの参照 static int idleState = Animator.StringToHash("Base Layer.Idle"); static int locoState = Animator.StringToHash("Base Layer.Locomotion"); static int jumpState = Animator.StringToHash("Base Layer.Jump"); static int restState = Animator.StringToHash("Base Layer.Rest"); // 初期化 void Start () { // Animatorコンポーネントを取得する anim = GetComponent<Animator>(); // CapsuleColliderコンポーネントを取得する(カプセル型コリジョン) col = GetComponent<CapsuleCollider>(); rb = GetComponent<Rigidbody>(); //メインカメラを取得する cameraObject = GameObject.FindWithTag("MainCamera"); // CapsuleColliderコンポーネントのHeight、Centerの初期値を保存する orgColHight = col.height; orgVectColCenter = col.center; } // 以下、メイン処理.リジッドボディと絡めるので、FixedUpdate内で処理を行う. void FixedUpdate () { float h = Input.GetAxis("Horizontal"); // 入力デバイスの水平軸をhで定義 float v = Input.GetAxis("Vertical"); // 入力デバイスの垂直軸をvで定義 anim.SetFloat("Speed", v); // Animator側で設定している"Speed"パラメタにvを渡す anim.SetFloat("Direction", h); // Animator側で設定している"Direction"パラメタにhを渡す anim.speed = animSpeed; // Animatorのモーション再生速度に animSpeedを設定する currentBaseState = anim.GetCurrentAnimatorStateInfo(0); // 参照用のステート変数にBase Layer (0)の現在のステートを設定する rb.useGravity = true;//ジャンプ中に重力を切るので、それ以外は重力の影響を受けるようにする // 以下、キャラクターの移動処理 velocity = new Vector3(0, 0, v); // 上下のキー入力からZ軸方向の移動量を取得 // キャラクターのローカル空間での方向に変換 velocity = transform.TransformDirection(velocity); //以下のvの閾値は、Mecanim側のトランジションと一緒に調整する if (v > 0.1) { velocity *= forwardSpeed; // 移動速度を掛ける } else if (v < -0.1) { velocity *= backwardSpeed; // 移動速度を掛ける } if (Input.GetButtonDown("Jump")) { // スペースキーを入力したら //アニメーションのステートがLocomotionの最中のみジャンプできる if (currentBaseState.nameHash == locoState){ //ステート遷移中でなかったらジャンプできる if(!anim.IsInTransition(0)) { rb.AddForce(Vector3.up * jumpPower, ForceMode.VelocityChange); anim.SetBool("Jump", true); // Animatorにジャンプに切り替えるフラグを送る } } } // 上下のキー入力でキャラクターを移動させる transform.localPosition += velocity * Time.fixedDeltaTime; // 左右のキー入力でキャラクタをY軸で旋回させる transform.Rotate(0, h * rotateSpeed, 0); // 以下、Animatorの各ステート中での処理 // Locomotion中 // 現在のベースレイヤーがlocoStateの時 if (currentBaseState.nameHash == locoState){ //カーブでコライダ調整をしている時は、念のためにリセットする if(useCurves){ resetCollider(); } } // JUMP中の処理 // 現在のベースレイヤーがjumpStateの時 else if(currentBaseState.nameHash == jumpState) { cameraObject.SendMessage("setCameraPositionJumpView"); // ジャンプ中のカメラに変更 // ステートがトランジション中でない場合 if(!anim.IsInTransition(0)) { // 以下、カーブ調整をする場合の処理 if(useCurves){ // 以下JUMP00アニメーションについているカーブJumpHeightとGravityControl // JumpHeight:JUMP00でのジャンプの高さ(0〜1) // GravityControl:1⇒ジャンプ中(重力無効)、0⇒重力有効 float jumpHeight = anim.GetFloat("JumpHeight"); float gravityControl = anim.GetFloat("GravityControl"); if(gravityControl > 0) rb.useGravity = false; //ジャンプ中の重力の影響を切る // レイキャストをキャラクターのセンターから落とす Ray ray = new Ray(transform.position + Vector3.up, -Vector3.up); RaycastHit hitInfo = new RaycastHit(); // 高さが useCurvesHeight 以上ある時のみ、コライダーの高さと中心をJUMP00アニメーションについているカーブで調整する if (Physics.Raycast(ray, out hitInfo)) { if (hitInfo.distance > useCurvesHeight) { col.height = orgColHight - jumpHeight; // 調整されたコライダーの高さ float adjCenterY = orgVectColCenter.y + jumpHeight; col.center = new Vector3(0, adjCenterY, 0); // 調整されたコライダーのセンター } else{ // 閾値よりも低い時には初期値に戻す(念のため) resetCollider(); } } } // Jump bool値をリセットする(ループしないようにする) anim.SetBool("Jump", false); } } // IDLE中の処理 // 現在のベースレイヤーがidleStateの時 else if (currentBaseState.nameHash == idleState) { //カーブでコライダ調整をしている時は、念のためにリセットする if(useCurves){ resetCollider(); } // スペースキーを入力したらRest状態になる if (Input.GetButtonDown("Jump")) { anim.SetBool("Rest", true); } } // REST中の処理 // 現在のベースレイヤーがrestStateの時 else if (currentBaseState.nameHash == restState) { //cameraObject.SendMessage("setCameraPositionFrontView"); // カメラを正面に切り替える // ステートが遷移中でない場合、Rest bool値をリセットする(ループしないようにする) if(!anim.IsInTransition(0)) { anim.SetBool("Rest", false); } } } void OnGUI() { GUI.Box(new Rect(Screen.width -260, 10 ,250 ,150), "Interaction"); GUI.Label(new Rect(Screen.width -245,30,250,30),"Up/Down Arrow : Go Forwald/Go Back"); GUI.Label(new Rect(Screen.width -245,50,250,30),"Left/Right Arrow : Turn Left/Turn Right"); GUI.Label(new Rect(Screen.width -245,70,250,30),"Hit Space key while Running : Jump"); GUI.Label(new Rect(Screen.width -245,90,250,30),"Hit Spase key while Stopping : Rest"); GUI.Label(new Rect(Screen.width -245,110,250,30),"Left Control : Front Camera"); GUI.Label(new Rect(Screen.width -245,130,250,30),"Alt : LookAt Camera"); } // キャラクターのコライダーサイズのリセット関数 void resetCollider() { // コンポーネントのHeight、Centerの初期値を戻す col.height = orgColHight; col.center = orgVectColCenter; } }看下UnityChanControlScriptWithRgidBody.cs这个类,UnityChan这个插件自带了日文和英文两种语言的文档,代码中注释也相当详细,代码也并不难懂,这里我大致的分析下,这段代码开头,
[RequireComponent(typeof (Animator))] [RequireComponent(typeof (CapsuleCollider))] [RequireComponent(typeof (Rigidbody))]
使得人物预制件需要3个系统组件来支持,作用呢,animator是u3d全新的动画系统的控制组件,CapsuleCollider是一个包裹人物预制件的碰撞体,而最后那个是刚体系统,
代码的FixedUpdate()方法中主要是anim.SetFloat("Speed", v);这种动画控制代码那么,具体代码是怎么控制的呢,我们看下animator中载入的控制器
我们可以看到控制器默认动作未Idle,而通过迁移线与其他动作相连,而左下方提供了控制动作变化的变量,我们就是通过变量的控制来达到动作的转换的,
我们以Jump变量为例,代码中if (Input.GetButtonDown("Jump")){}也就是空格按下,这时候如果符合条件,如人物正在跑动,那么anim.SetBool("Jump", true);这样动作控制就完成了,而另外一个类FaceUpdate.cs这个类非常简单
using UnityEngine; using System.Collections; public class FaceUpdate : MonoBehaviour { public AnimationClip[] animations; Animator anim; public float delayWeight; void Start () { anim = GetComponent<Animator> (); } void OnGUI () { foreach (var animation in animations) { if (GUILayout.Button (animation.name)) { anim.CrossFade (animation.name, 0); } } } float current = 0; void Update () { if (Input.GetMouseButton (0)) { current = 1; } else { current = Mathf.Lerp (current, 0, delayWeight); } anim.SetLayerWeight (1, current); } }其实就是个由屏幕按钮控制人物表情,播放的功能,这里需要注意一点可能就是一个不太注意的细节就是
这个遮罩,如果按照这个系统做的表情播放不出来,那么建议去注意下这个,其他的因为这个代码很好理解,也没什么可说的,如果真的就不懂,网上有一套UnityChan的11集的免费视频教程,大家可以去看看,里面包括如果用maya来建立人物都写得很详细,最后我们就看看如何利用这些代码呢?首先我们在网上下载一个人物模型
我们以韩菱纱为例,注意我们使用的模型可以没有绑定动作,但必须顶点骨骼绑定完成的,否则,我们导出的fbx文件将是石膏模,我们在场景中是无法使用的,具体怎么导出,在菜单里找导出,然后选fbx文件格式就行了,当然导其他的格式也可以,但需要注意的是,要是u3d支持的3d格式,然后我们把导好的模型复制进工程文件夹,
,记得先把贴图赋一下,之后,我们点击hls0这个fbx文件我们设置生成Avatar
具体为什么设置avatar我建议不明白的小伙伴去看这篇文章配置Avatar,然后把hls0做成预制件,具体做法就是拖到
就可以了,之后我们在属性窗口中,绑定我们需要的
里面的参数需要自己按照自己的模型来调整
关于数据我们可以按照需要自己调整,比如我们可以改变JumpPower来改变化身跳跃的高度,其实这个场景中还有一个比较重要的预制件,
就是摄像机,我们依靠这个来达到相机跟谁化身效果,但,untiychan里面的两个摄像机控制方式都跟我们平时玩的3剑游戏控制方式不同,所以在我的仙剑Demo中没有用到这个预制件,等后面我会讲解我们在Demo中用到的镜头跟随方法,最后我们看下我们最终做的人物是什么样的吧,
相关文章推荐
- 从今天起开始学习如何制作游戏
- 如何制作一款HTML5 RPG游戏引擎——第五篇,人物&人物特效
- 如何制作一款HTML5 RPG游戏引擎——第五篇,人物&人物特效
- 黑莓开发新手入门教学帖,如何制作一个能控制LED颜色的程序(四)
- 如何实现串口控制 我刚开始学delphi 希望得到帮助
- 如何制作一款HTML5 RPG游戏引擎——第五篇,人物&人物特效
- Adobe DPS正式版的制作平板出版物 1 – 如何开始
- 今天开始试用SVN进行版本控制
- 黑莓开发新手入门教学帖,如何制作一个能控制LED颜色的程序(三)
- 今天开始学PID电机控制,这个作者写得很不错,和大家分享一下~~~ PID控制算法通俗理解 作者:whut_wj 来源:http://blog.eccn.com/space.php?uid=35
- Unity3d制作虚拟按钮控制人物移动
- 黑莓开发新手入门教学帖,如何制作一个能控制LED颜色的程序(五)
- 今天开始学习信息安全以及如何简单的写一个网页
- 如何实现串口控制 我刚开始学delphi 希望得到帮助
- 马云说,“如果我今天开始创业,首先想的是如何利用好腾讯或阿里巴巴”
- 如何制作一款HTML5 RPG游戏引擎——第五篇,人物&人物特效
- 黑莓开发新手入门教学帖,如何制作一个能控制LED颜色的程序(六)
- 自行控制loadrunner的socket协议性能测试 (转) 一前言 二任务的提出 三实现方案讨论 四技术要点讲解 如何开始录制一个最简单的收发数据包脚本 写日志文件 一行一行读数据包文件 字
- 如何制作一个可控制的人体骨骼模型
- 今天开始研究c#控制word