Unity實(shí)現(xiàn)主角移動(dòng)與攝像機(jī)跟隨
在游戲開(kāi)發(fā)中,主角需要通過(guò)跑地圖來(lái)通關(guān)升級(jí),本章主要介紹主角的移動(dòng)和攝像跟隨的操作。
主角移動(dòng)
角色位移通過(guò)主角的骨骼動(dòng)畫(huà)控制(后續(xù)文章會(huì)詳細(xì)介紹狀態(tài)機(jī)的使用),這里只需要勾選Animator動(dòng)畫(huà)控制器下Apply Root Motion讓角色的移動(dòng)受動(dòng)畫(huà)控制。
通過(guò)碰撞檢測(cè)來(lái)判斷哪些位置主角可以移動(dòng),哪些位置角色不能行走,這里需要兩個(gè)組件Rigidbody剛體,和Collider碰撞組件
- Rigidbody:為游戲賦予物理屬性,在游戲中只有添加了剛體的物體才能模擬物理屬性,如重力等。

如上圖所示,各參數(shù)含義如下:
Mass 質(zhì)量:?jiǎn)挝蝗我?。但是官方建議物體的質(zhì)量差不要超過(guò)100倍
Drag 阻力:物體移動(dòng)時(shí)受到的空氣阻力,0表示無(wú)阻力
Angular Drag 角阻力:當(dāng)受扭力時(shí)物體旋轉(zhuǎn)時(shí)受到的空氣阻力,同樣0表示無(wú)阻力
Use Gravity 使用重力:表示該物體是否受重力影響
Is Kinematic 是否是運(yùn)動(dòng)學(xué):游戲?qū)ο笫欠褡裱\(yùn)動(dòng)學(xué)規(guī)律,如果激活不在受物理引擎驅(qū)動(dòng)(動(dòng)畫(huà)控制移動(dòng),不勾選)
Interpolate 插值:物體運(yùn)動(dòng)的插值模式
Collision Detection 碰撞檢測(cè):碰撞檢測(cè)模式。用于避免高速物體穿過(guò)其它物體未發(fā)生碰撞
Constraint 約束:對(duì)剛體運(yùn)動(dòng)的約束,可以鎖定位置和旋轉(zhuǎn)的x、y、z軸
- Collider:碰撞器有很多中,需要根據(jù)實(shí)際的需要選擇不同的觸發(fā)器,這里只是簡(jiǎn)單的介紹其基礎(chǔ)功能

Is Trigger 觸發(fā)器:勾選該選項(xiàng),碰撞用于觸發(fā)事件 OnTriggerEnter、OnTriggerExit、OnTriggerStay并被物理引擎所忽略
Input.GetAxis(args) :獲取移動(dòng)方位。
float h = Input.GetAxis("Horizontal");//對(duì)應(yīng)鍵盤(pán)的上下
float v = Input.GetAxis("Vertical");//對(duì)應(yīng)鍵盤(pán)的左右
通過(guò)插值運(yùn)算,控制主角平滑的轉(zhuǎn)向和移動(dòng):
void Update()
{
role.SetBool(StealthConst.SNEAK, Input.GetKey(KeyCode.LeftShift));
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
if (Mathf.Abs(h) > 0.1f || Mathf.Abs(v) > 0.1f)
{
//5.6由動(dòng)畫(huà)控制器中的參數(shù)決定
float currentSpeed = Mathf.Lerp(role.GetFloat(StealthConst.SPEED), 5.6f, moveSpeed * Time.deltaTime);
role.SetFloat(StealthConst.SPEED, currentSpeed);//Animator通過(guò)速度控制移動(dòng)的快慢
Vector3 targetDir = new Vector3(h, 0, v);
//Vector3.up相當(dāng)于(0,1,0)繞著Y軸,看向目標(biāo)位置
Quaternion newRotation = Quaternion.LookRotation(targetDir, Vector3.up);
transform.rotation = Quaternion.Lerp(transform.rotation, newRotation, rotateSpeed * Time.deltaTime);
}
else
{
role.SetFloat(StealthConst.SPEED, 0);
}
}
攝像機(jī)跟隨
攝像機(jī)跟隨的原理十分簡(jiǎn)單,在場(chǎng)景設(shè)計(jì)中將相機(jī)和主角的相對(duì)位置保持固定,跟隨主角移動(dòng)即可。但是有種特殊情況,當(dāng)主角移動(dòng)到墻邊,被遮擋后如果還是保持原來(lái)的相對(duì)位置,則視野中將觀察不到主角,這時(shí)需要?jiǎng)討B(tài)的調(diào)整攝像機(jī)的位置。

這里將采用射線碰撞的方式來(lái)檢查,從相機(jī)的位置開(kāi)始,到主角正上方截止,平均劃分3個(gè)點(diǎn),依次從五個(gè)點(diǎn)分別發(fā)射一條射線,當(dāng)射線能直接碰到主角或者沒(méi)有碰到說(shuō)明主角在攝像的范圍內(nèi),將攝像機(jī)平滑的移動(dòng)到能夠看到主角的位置即可。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowPlayer : MonoBehaviour
{
private Vector3 offset;
public Transform role;
public float moveSpeed = 3;
public float rotateSpeed = 3;
// Start is called before the first frame update
void Start()
{
offset = transform.position - role.position;
offset = new Vector3(0, offset.y, offset.z);
}
// Update is called once per frame
void Update()
{
Vector3 beginPos = role.position + offset;//攝像機(jī)正常偏移位置,起點(diǎn)
Vector3 endPos = role.position + offset.magnitude * Vector3.up;//offset.magnitude向量的長(zhǎng)度
///從起點(diǎn)到終點(diǎn)分別取3個(gè)點(diǎn),通過(guò)射線判斷攝像機(jī)是否有遮擋
Vector3[] posArr = new Vector3[] {
beginPos,
Vector3.Lerp(beginPos,endPos,0.25f),
Vector3.Lerp(beginPos,endPos,0.5f),
Vector3.Lerp(beginPos,endPos,0.75f),
endPos
};
Vector3 targetPos = posArr[0];
foreach (var pos in posArr)
{
RaycastHit hitInfo;
///第一個(gè)參數(shù)射線的起點(diǎn),第二個(gè)參數(shù)射線的方向
if (Physics.Raycast(pos, role.position - pos, out hitInfo))
{
if (hitInfo.collider.tag == StealthConst.PLAYER)
{
targetPos = pos;
break;
}
else
{
continue;
}
}
else
{
targetPos = pos;
break;
}
}
this.transform.position = Vector3.Lerp(transform.position,targetPos,Time.deltaTime*moveSpeed);//通過(guò)插值平滑移動(dòng)
Quaternion nowRotation = transform.rotation;
this.transform.LookAt(role.position);//攝像機(jī)轉(zhuǎn)向目標(biāo)
this.transform.rotation = Quaternion.Lerp(nowRotation, transform.rotation, Time.deltaTime * rotateSpeed);//通過(guò)插曲平滑旋轉(zhuǎn)
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
asp.net實(shí)現(xiàn)遍歷Request的信息操作示例
這篇文章主要介紹了asp.net實(shí)現(xiàn)遍歷Request的信息操作,涉及asp.net針對(duì)請(qǐng)求信息相關(guān)操作打印操作技巧,需要的朋友可以參考下2020-03-03
C#實(shí)現(xiàn)多線程寫(xiě)入同一個(gè)文件的方法
這篇文章主要介紹了C#實(shí)現(xiàn)多線程寫(xiě)入同一個(gè)文件的方法,涉及C#多線程操作文件讀寫(xiě)的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08
C#操作mysql數(shù)據(jù)庫(kù)的代碼實(shí)例
這篇文章為大家提供了一個(gè)C#操作mysql數(shù)據(jù)庫(kù)的實(shí)例,大家可以參考使用2013-11-11
C#實(shí)現(xiàn)的簡(jiǎn)單鏈表類實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)的簡(jiǎn)單鏈表類,涉及C#針對(duì)鏈表的定義、實(shí)現(xiàn)及鏈表節(jié)點(diǎn)的增加、刪除與修改技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08
Unity2021發(fā)布WebGL與網(wǎng)頁(yè)交互問(wèn)題的解決
本文主要介紹了Unity2021發(fā)布WebGL與網(wǎng)頁(yè)交互問(wèn)題的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05

