博客
关于我
Unity手游之路<七>角色控制器
阅读量:797 次
发布时间:2023-03-28

本文共 6369 字,大约阅读时间需要 21 分钟。

Unity角色控制器与视角实现技术指南

在Unity游戏开发中,角色控制器与视角的实现是实现游戏逻辑的重要环节。本文将详细介绍如何通过Unity的Character Controller组件来控制角色移动,并结合摄像机控制器实现第一人称和第三人称视角的效果。

角色控制器的核心功能

Character Controller组件是Unity中用于控制角色移动的核心组件。它能够在受制于碰撞的情况下自动处理角色运动,而无需手动处理刚体或受力情况。主要特点包括:

  • 无需处理重力:Character Controller会自动处理Y轴方向的重力影响,因此我们只需通过调用Move函数来控制角色移动。
  • 支持碰撞检测:在移动过程中,角色会自动检测并避开周围的物体。
  • 灵活的移动控制:支持通过SimpleMove和Move函数实现不同类型的移动。
  • SimpleMove和Move函数的区别

    • SimpleMove:忽略Y轴速度,适合水平移动。
    • Move:支持三维移动,包括Y轴的重力控制。

    以下是使用SimpleMove和Move函数的示例代码:

    CharacterController controller = GetComponent
    ();Vector3 forward = transform.TransformDirection(Vector3.forward);float curSpeed = speed * Input.GetAxis("Vertical");controller.SimpleMove(forward * curSpeed);

    视角控制器的实现

    在游戏中,视角的控制是玩家体验感的重要因素。Unity提供了两种常见的视角控制器:第一人称和第三人称。

    第一人称控制器

    第一人称视角是许多经典游戏(如CS:GO)使用的视角类型。摄像机的位置与玩家角色保持一致,视角随着角色移动而移动。

    实现步骤:

  • 删除默认的摄像机。
  • 创建地形(Terrain)。
  • 将First Person Controller组件添加到角色模型上。
  • 调整摄像机位置和方向,实现视角跟随效果。
  • 第三人称控制器

    第三人称视角常用于角色扮演游戏(如Dota)。摄像机距离角色有一定距离,能够清晰观察角色动作。

    实现步骤:

  • 创建地形。
  • 将Third Person Controller组件添加到角色模型上。
  • 设置摄像机为Main Camera。
  • 调整Third Person Camera参数,实现视角跟随效果。
  • 核心代码解读

    第一人称角色控制器脚本

    function Update() {    // 获取键盘方向    var directionVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));    // 处理方向向量    if (directionVector != Vector3.zero) {        var directionLength = directionVector.magnitude;        directionVector = directionVector / directionLength;        directionLength = Mathf.Min(1, directionLength);        directionLength = directionLength * directionLength;        directionVector = directionVector * directionLength;    }    // 设置移动方向    motor.inputMoveDirection = transform.rotation * directionVector;    // 处理跳跃    motor.inputJump = Input.GetButton("Jump");}

    第三人称角色控制器脚本

    function Update() {    // 处理跳跃逻辑    if (Input.GetButtonDown("Jump")) {        lastJumpButtonTime = Time.time;    }    // 更新角色方向    UpdateSmoothedMovementDirection();    // 处理重力和跳跃    ApplyGravity();    ApplyJumping();    // 计算实际动作    var movement = moveDirection * moveSpeed + Vector3(0, verticalSpeed, 0) + inAirVelocity;    movement *= Time.deltaTime;    // 移动角色    var controller : CharacterController = GetComponent(CharacterController);    collisionFlags = controller.Move(movement);    // 处理动画    if(_animation) {        // 根据角色状态处理动画        if(_characterState == CharacterState.Jumping) {            // 处理跳跃动画            if(!jumpingReachedApex) {                _animation[jumpPoseAnimation.name].speed = jumpAnimationSpeed;                _animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;                _animation.CrossFade(jumpPoseAnimation.name);            } else {                _animation[jumpPoseAnimation.name].speed = -landAnimationSpeed;                _animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;                _animation.CrossFade(jumpPoseAnimation.name);            }        } else {            // 处理站立、奔跑、疾走等状态动画            if(controller.velocity.sqrMagnitude < 0.1) {                _animation.CrossFade(idleAnimation.name);            } else {                if(_characterState == CharacterState.Running) {                    _animation[runAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, runMaxAnimationSpeed);                    _animation.CrossFade(runAnimation.name);                } else if(_characterState == CharacterState.Trotting) {                    _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, trotMaxAnimationSpeed);                    _animation.CrossFade(walkAnimation.name);                } else if(_characterState == CharacterState.Walking) {                    _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, walkMaxAnimationSpeed);                    _animation.CrossFade(walkAnimation.name);                }            }        }    }    // 处理旋转    if (IsGrounded()) {        transform.rotation = Quaternion.LookRotation(moveDirection);    } else {        var xzMove = movement;        xzMove.y = 0;        if (xzMove.sqrMagnitude > 0.001) {            transform.rotation = Quaternion.LookRotation(xzMove);        }    }    // 处理跳跃状态    if (IsGrounded()) {        lastGroundedTime = Time.time;        inAirVelocity = Vector3.zero;        if (jumping) {            jumping = false;            SendMessage("DidLand", SendMessageOptions.DontRequireReceiver);        }    }}

    摄像机控制器脚本

    function Apply(dummyTarget : Transform, dummyCenter : Vector3) {    // 处理摄像机旋转    if (!controller) {        return;    }    // 计算目标中心和顶点    var targetCenter = _target.position + centerOffset;    var targetHead = _target.position + headOffset;    // 计算当前角度    var originalTargetAngle = _target.eulerAngles.y;    var currentAngle = cameraTransform.eulerAngles.y;    // 处理快速旋转    if (Input.GetButton("Fire2")) {        snap = true;    }    if (snap) {        // 检查是否接近目标角度        if (AngleDistance(currentAngle, originalTargetAngle) < 3.0) {            snap = false;        }        // 平滑旋转        currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, angleVelocity, snapSmoothLag, snapMaxSpeed);    }    // 处理普通视角    else {        // 延迟处理        if (controller.GetLockCameraTimer() < lockCameraTimeout) {            targetAngle = currentAngle;        }        // 后退时锁定视角        if (AngleDistance(currentAngle, targetAngle) > 160 && controller.IsMovingBackwards()) {            targetAngle += 180;            // 平滑旋转            currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, angleVelocity, angularSmoothLag, angularMaxSpeed);        }    }    // 处理跳跃时的视角    if (controller.IsJumping()) {        // 调整摄像机高度        var newTargetHeight = targetCenter.y + height;        if (newTargetHeight < targetHeight || newTargetHeight - targetHeight > 5) {            targetHeight = targetCenter.y + height;        }    }    // 调整摄像机位置和高度    var currentHeight = cameraTransform.position.y;    currentHeight = Mathf.SmoothDamp(currentHeight, targetHeight, heightVelocity, heightSmoothLag);    // 更新摄像机位置    cameraTransform.position = targetCenter;    cameraTransform.position += currentRotation * Vector3.back * distance;    cameraTransform.position.y = currentHeight;    // 保持摄像机朝向目标    SetUpRotation(targetCenter, targetHead);}

    总结

    通过使用Unity的Character Controller组件和自定义脚本,我们可以轻松实现角色和摄像机的移动控制。Character Controller能够自动处理碰撞和重力,简化了游戏逻辑开发。无论是第一人称还是第三人称视角,通过合理配置摄像机控制器组件,都能实现理想的视角效果。

    转载地址:http://othfk.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现检查给定的字符串是否在kebabcase中算法(附完整源码)
    查看>>
    Objective-C实现检查给定的字符串是否在snake_case中算法(附完整源码)
    查看>>
    Objective-C实现检查给定的字符串是否是扁平(全部小写)的算法(附完整源码)
    查看>>
    Objective-C实现检检查回文字符串(区分大小写)算法(附完整源码)
    查看>>
    Objective-C实现检测U盘的插入与拔出 (附完整源码)
    查看>>
    Objective-C实现检测列表中的循环算法(附完整源码)
    查看>>
    Objective-C实现检测耳机插拔功能(附完整源码)
    查看>>
    Objective-C实现模拟键盘鼠标(附完整源码)
    查看>>
    Objective-C实现模板方法模式(附完整源码)
    查看>>
    Objective-C实现欧几里得距离(附完整源码)
    查看>>
    Objective-C实现欧几里得距离(附完整源码)
    查看>>
    Objective-C实现欧拉路径和欧拉回路算法(附完整源码)
    查看>>
    Objective-C实现正向CMDShell(附完整源码)
    查看>>
    Objective-C实现正数num使用递归找到它的二进制算法(附完整源码)
    查看>>
    Objective-C实现水波纹显示效果(附完整源码)
    查看>>
    Objective-C实现求 1 到 20 的所有数整除的最小正数算法 (附完整源码)
    查看>>
    Objective-C实现求1000以内的全部亲密数(附完整源码)
    查看>>
    Objective-C实现求a的逆元x(附完整源码)
    查看>>
    Objective-C实现求squareDifference平方差算法 (附完整源码)
    查看>>
    Objective-C实现求一个数的位数之和算法(附完整源码)
    查看>>