Unity实现主角移动与摄像机跟随
作者:双鱼-布衣 发布时间:2023-09-14 09:32:05
在游戏开发中,主角需要通过跑地图来通关升级,本章主要介绍主角的移动和摄像跟随的操作。
主角移动
角色位移通过主角的骨骼动画控制(后续文章会详细介绍状态机的使用),这里只需要勾选Animator动画控制器下Apply Root Motion让角色的移动受动画控制。
通过碰撞检测来判断哪些位置主角可以移动,哪些位置角色不能行走,这里需要两个组件Rigidbody刚体,和Collider碰撞组件
Rigidbody:为游戏赋予物理属性,在游戏中只有添加了刚体的物体才能模拟物理属性,如重力等。
如上图所示,各参数含义如下:
Mass 质量:单位任意。但是官方建议物体的质量差不要超过100倍
Drag 阻力:物体移动时受到的空气阻力,0表示无阻力
Angular Drag 角阻力:当受扭力时物体旋转时受到的空气阻力,同样0表示无阻力
Use Gravity 使用重力:表示该物体是否受重力影响
Is Kinematic 是否是运动学:游戏对象是否遵循运动学规律,如果激活不在受物理引擎驱动(动画控制移动,不勾选)
Interpolate 插值:物体运动的插值模式
Collision Detection 碰撞检测:碰撞检测模式。用于避免高速物体穿过其它物体未发生碰撞
Constraint 约束:对刚体运动的约束,可以锁定位置和旋转的x、y、z轴
Collider:碰撞器有很多中,需要根据实际的需要选择不同的触发器,这里只是简单的介绍其基础功能
Is Trigger 触发器:勾选该选项,碰撞用于触发事件 OnTriggerEnter、OnTriggerExit、OnTriggerStay并被物理引擎所忽略
Input.GetAxis(args) :获取移动方位。
float h = Input.GetAxis("Horizontal");//对应键盘的上下
float v = Input.GetAxis("Vertical");//对应键盘的左右
通过插值运算,控制主角平滑的转向和移动:
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由动画控制器中的参数决定
float currentSpeed = Mathf.Lerp(role.GetFloat(StealthConst.SPEED), 5.6f, moveSpeed * Time.deltaTime);
role.SetFloat(StealthConst.SPEED, currentSpeed);//Animator通过速度控制移动的快慢
Vector3 targetDir = new Vector3(h, 0, v);
//Vector3.up相当于(0,1,0)绕着Y轴,看向目标位置
Quaternion newRotation = Quaternion.LookRotation(targetDir, Vector3.up);
transform.rotation = Quaternion.Lerp(transform.rotation, newRotation, rotateSpeed * Time.deltaTime);
}
else
{
role.SetFloat(StealthConst.SPEED, 0);
}
}
摄像机跟随
摄像机跟随的原理十分简单,在场景设计中将相机和主角的相对位置保持固定,跟随主角移动即可。但是有种特殊情况,当主角移动到墙边,被遮挡后如果还是保持原来的相对位置,则视野中将观察不到主角,这时需要动态的调整摄像机的位置。
这里将采用射线碰撞的方式来检查,从相机的位置开始,到主角正上方截止,平均划分3个点,依次从五个点分别发射一条射线,当射线能直接碰到主角或者没有碰到说明主角在摄像的范围内,将摄像机平滑的移动到能够看到主角的位置即可。
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;//摄像机正常偏移位置,起点
Vector3 endPos = role.position + offset.magnitude * Vector3.up;//offset.magnitude向量的长度
///从起点到终点分别取3个点,通过射线判断摄像机是否有遮挡
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;
///第一个参数射线的起点,第二个参数射线的方向
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);//通过插值平滑移动
Quaternion nowRotation = transform.rotation;
this.transform.LookAt(role.position);//摄像机转向目标
this.transform.rotation = Quaternion.Lerp(nowRotation, transform.rotation, Time.deltaTime * rotateSpeed);//通过插曲平滑旋转
}
}
来源:https://blog.csdn.net/qq_19428987/article/details/114521294


猜你喜欢
- 安装Jenkins提示:首先Jenkins安装方式有2中,一种是yum安装,另一种是使用war的方式进行安装(war就需要安装tomcat)
- 前言在之前的文章我们复习了 ViewGroup 的测量与布局,那么我们这一篇效果就可以在之前的基础上实现一个灵活的九宫格布局。那么一个九宫格
- 这个功能没什么可介绍的,大家都懂,直接上代码了。。实现功能选择多个文件压缩成ZIP文件和解压ZIP文件开发环境开发工具: Visual St
- 1、super的使用:(1)super是一个关键字。(2)super和this很类似,我们对比着学习。2、先复习一下this关键字的使用。(
- 笔者计划为大家介绍分布式文件系统,用于存储应用的图片、word、excel、pdf等文件。在开始介绍分布式文件系统之前,为大家介绍一下使用本
- 前言在这篇文章里,最后总结处,我说了会讲讲循环依赖中,其中一个类添加@Async有可能会导致注入失败而抛异常的情况,今天就分析一下。一、异常
- 在Android开发过程中,如果Android系统自带的属性不能满足我们日常开发的需求,那么就需要我们给系统控件添加额外的属性了。假如有个需
- android线程消息机制主要由Handler,Looper,Message和MessageQuene四个部分组成。平常在开发中,我们常用来
- 前言安卓6.0之后,一些敏感权限需要进行动态请求,虽说编写请求授权代码并不难,但是每次一需要权限就需要在视图中添加一段代码,严重影响代码美观
- Java中的Runnable,Callable,Future,FutureTask的比较Java中存在Runnable、Callable、F
- 安装配置完Java的jdk,下面就开始写第一个java程序--hello World.用来在控制台输出“Hello World”。首先,我们
- 1、什么是const? 常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。(当然,我们可以偷梁
- 一个Java程序的执行要经过编译和执行(解释)这两个步骤,同时Java又是面向对象的编程语言。当子类和父类存在同一个方法,子类重写了父类的方
- 1、多态性多态性是面向对象的最后一个特征,它本身主要分为两个方面: 方法的多态性:重载与覆写1、重载:同一个方法名称,根据参数类型以及个数完
- 首先要解析string类型的xml必须先要将其转化成dom格式,然后再进行解析取值,如下是解析代码示例:package com.compan
- 使用 DateFormat 格式化日期、时间DateFormat 也是一个抽象类,它也提供了如下几个类方法用于获取 DateFormat 对
- 安装方式:使用vs自带的nuget管理工具,搜索AutoMapper ,选择第一个安装到你的项目即可。先说说DTODTO是个什么东东?DTO
- 异常处理机制1、抛出异常2、捕获异常3、异常处理五个关键字:try、catch、finally、throw、throws注意:假设要捕获多个
- 需求在配置类中,从application.properties中读取一个复杂list。如List<Person>或者初始化一个m
- 计算两点之间的距离然后在控制台输出,这个题目还是挺简单的。下面我们来看看具体代码。package com.swift;import java