Unity组件开发--相机跟随角色和旋转

这篇具有很好参考价值的文章主要介绍了Unity组件开发--相机跟随角色和旋转。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.相机跟随组件,节点:

Unity组件开发--相机跟随角色和旋转,unity组件开发,unity,游戏引擎,游戏程序

Unity组件开发--相机跟随角色和旋转,unity组件开发,unity,游戏引擎,游戏程序

2.相机跟随组件脚本:

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Burst.Intrinsics;
using UnityEngine;
using UnityEngine.UI;

public class CameraFollow : Singleton<CameraFollow> {
    public Transform firstAngleTarget; //第一人称跟随的目标
    public Transform threeAngleTarget; //第三人称跟随的目标
    public float radius;
    public float polarDeg;
    public float elevationDeg;
    private Transform target;
    public bool isLookAt;

    public float lerpSpeed = 0;

    //是否第一人称视角
    private bool isFirstAngle = false;

    LayerMask mask;
    /// <summary>
    /// 极坐标转换成笛卡尔坐标
    /// </summary>
    /// <param name="radius"></param>
    /// <param name="angle"></param>
    /// <returns></returns>
    /// 

    private bool isDriven;

    private void Awake() {
        EventManager.Instance.AddListener(EventName.PlayerDriving, (s, e) => {  //开车事件触发
            var arg = e as PlayerDrivingEventArgs;
            if (arg.driveObj && arg.driveObj.GetComponent<VehicleBase>() && arg.driveObj.GetComponent<VehicleBase>().driveCam) {
                gameObject.SetActive(false);
            }
            else {
                isDriven = true;
            }
        });

        EventManager.Instance.AddListener(EventName.PlayerDown, (s, e) => {  //开车事件触发
            var arg = e as PlayerDrivingEventArgs;                                              //isDriven = false;
            if (arg.driveObj && arg.driveObj.GetComponent<VehicleBase>() && arg.driveObj.GetComponent<VehicleBase>().driveCam) {
                gameObject.SetActive(true);
            }
            else {
                isDriven = false;
            }
        });
    }

    private void Start()
    {

        mask.value = (1 << LayerMask.NameToLayer("Ground")) | (1 << LayerMask.NameToLayer("Wall"));
        this.target = this.threeAngleTarget;
        EventManager.Instance.AddListener(EventName.ChangeAngle, changeAngle);

        var offset = SphericalToCartesian(radius, DegreeToRadian(polarDeg), DegreeToRadian(elevationDeg));
        //transform.position = Vector3.Lerp(transform.position, target.position + offset, Time.deltaTime * 10);
        transform.position = target.position + offset;
    }

    private void changeAngle(object sender, EventArgs e) {
        var data = e as AngleChangeEventArgs;
        if (data != null) {
            if (data.angleIndex == 1) {
                this.target = this.firstAngleTarget;
                this.radius = 0;
                isFirstAngle = true;
                transform.position = target.position;
                transform.forward = target.forward;
            } else if (data.angleIndex == 3) {
                this.target = this.threeAngleTarget;
                this.radius = 6;
                isFirstAngle = false;
            }
        }
        Debug.Log("摄像机视角改变" + e);
    }
    public Vector2 PolarToCartesian(float radius, float angle) {
        float x = radius * Mathf.Cos(angle);
        float y = radius * Mathf.Sin(angle);
        return new Vector2(x, y);
    }

    public static float DegreeToRadian(float degree) {
        return degree * Mathf.Deg2Rad;
    }

    public static Vector3 SphericalToCartesian(float radius, float polar, float elevation) {
        float a = radius * Mathf.Cos(elevation);
        float x = a * Mathf.Cos(polar);
        float y = radius * Mathf.Sin(elevation);
        float z = a * Mathf.Sin(polar);
        return new Vector3(x, y, z);
    }

    public static void CartesianToSpherical(Vector3 cartesian, out float radius, out float polar, out float elevation) {
        radius = Mathf.Sqrt(Mathf.Pow(cartesian.x, 2) + Mathf.Pow(cartesian.y, 2) + Mathf.Pow(cartesian.z, 2));
        polar = Mathf.Atan2(cartesian.z, cartesian.x);
        elevation = Mathf.Asin(cartesian.y / radius);
    }



    void LateUpdate() {

        if (isDriven) {
            var offset = SphericalToCartesian(6f, DegreeToRadian(270), DegreeToRadian(-15));
            transform.position = Vector3.Lerp(transform.position, target.TransformPoint(target.localPosition + offset), Time.deltaTime * 3);
            //transform.position = target.TransformPoint(target.localPosition + offset);
            transform.LookAt(target);
            return;
        }

        if (isFirstAngle) {
            //var offset = SphericalToCartesian(radius, DegreeToRadian(polarDeg), DegreeToRadian(elevationDeg));
            target.eulerAngles = new Vector3(elevationDeg, -polarDeg, 0);
            transform.forward = target.forward;
            transform.position = target.position;
            if (PlayerController.Instance.animator) {
                var euler = PlayerController.Instance.animator.transform.eulerAngles;
                PlayerController.Instance.animator.transform.eulerAngles = new Vector3(euler.x, target.eulerAngles.y, euler.z);
            }

        }
       else {
            Ctrl_Cam_Move();
            CtrThird();
        }

       
       

        
    }

    void CtrThird() {

        var offset = SphericalToCartesian(radius, DegreeToRadian(polarDeg), DegreeToRadian(elevationDeg));
        //更新相机位置
        //transform.position = target.position + offset;
        transform.position = target.position + offset;
        //TODO:做成CAMERA NEAR OBJ,进行隐藏
        if (PlayerController.Instance.animator != null) PlayerController.Instance.animator.gameObject.SetActive(true);
        //计算完位置之后处理让镜头不会穿墙
        Vector3 direction = transform.position - target.position;
        float distance = direction.magnitude;
        direction.Normalize();
        RaycastHit hit;
        if (Physics.Raycast(target.transform.position, direction, out hit, distance, mask.value)) {
            var dstPos = hit.point - distance * distance * direction * 0.01f;
            var offsetDis = target.position - dstPos;
            CartesianToSpherical(offsetDis, out var compareRadius, out _, out _);
            if (compareRadius < 1f)  {
                if (PlayerController.Instance.animator != null)  PlayerController.Instance.animator.gameObject.SetActive(false);
            }
            transform.position = dstPos;

        }
        transform.eulerAngles = target.eulerAngles;

        if (isLookAt) {
            

            transform.LookAt(target);
            
        }
    }

    public void Ctrl_Cam_Move()
    {
        if (EditorModel.Instance.CurrentUnlock != null) { //解锁其他物体的时候,镜头不动, 要前后移动的是物体
            return;
        }

        if (Input.GetAxis("Mouse ScrollWheel") > 0)
        {
            //transform.Translate(Vector3.forward * 1f);//速度可调  自行调整
            radius = Math.Clamp(radius - 1.0f, 2, 15);
        }
        if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {
            //transform.Translate(Vector3.forward * -1f);//速度可调  自行调整
           
            radius = Math.Clamp(radius + 1.0f, 2, 15);
        }
    }
}

3.相机跟随角色视角旋转:文章来源地址https://www.toymoban.com/news/detail-791983.html


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class CameraRotate : MonoBehaviour
{

    public float speedH;
    //public float speedVertical;
    public bool isMobile;
    //[Range(0f, 1f)]
    //public float damping;
    CameraFollow cameraFollow;
    private float currentHorizontal;
    private float currentVertical;
    private Vector3 lastMousePosition;
    private bool isDragging;

    float time;
    private float velocityY;
    private float velocityX;


    PointerEventData eventDataCurrentPosition;
    //private bool isDragging;
    public static CameraRotate instance;
    private void Awake() {
        instance = this;
        //UI交互要禁用玩家的控制
        
        cameraFollow = Camera.main.GetComponent<CameraFollow>();
        currentHorizontal = cameraFollow.polarDeg;
        time = Time.realtimeSinceStartup;
    }

    // Start is called before the first frame update
    void Start() {
        
    }

    public void SetPolarDeg(float degree) {
        currentHorizontal = degree;
        cameraFollow.polarDeg = degree;
    }

    private bool IsPointerOverUIObject() {//判断是否点击的是UI,有效应对安卓没有反应的情况,true为UI


        
        if (eventDataCurrentPosition == null) {
            eventDataCurrentPosition = new PointerEventData(EventSystem.current);
        }

        eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
        

        

        return results.Count > 0;
    }

    // Update is called once per frame
    void LateUpdate() {

        //if (IsPointerOverUIObject()) {
        //    lastMousePosition = Input.mousePosition;
        //    return;//点击到UI不处理
        //}

        // 检查鼠标左键是否按下如果按下的那一下是在UI之上,则不让其旋转
        if (PlayerData.Instance.isRunningPC)
        {
            if (Input.GetMouseButtonDown(0) && IsPointerOverUIObject() == false)
            {
                // 记录鼠标点击位置
                lastMousePosition = Input.mousePosition;
                isDragging = true;
            }
            else if (Input.GetMouseButtonUp(0))
            {
                // 如果鼠标抬起,则需要重新按下鼠标来记录新的点击位置
                isDragging = false;
            }

        }
        else {
            if (Input.GetMouseButtonDown(0))
            {
                // 记录鼠标点击位置
                lastMousePosition = Input.mousePosition;
                isDragging = true;
            }
            else if (Input.GetMouseButtonUp(0))
            {
                // 如果鼠标抬起,则需要重新按下鼠标来记录新的点击位置
                isDragging = false;
            }

        }
        

      

        if (isDragging) {

            float speedHorizontal = speedH;
            float speedVertical = 0.1f;

            // 计算鼠标移动的增量
            Vector3 deltaMousePosition = Input.mousePosition - lastMousePosition;

            //Debug.Log("deltaMousePosition.x:" + deltaMousePosition.x + "deltaMousePosition.y:" + deltaMousePosition.y);
            // 计算水平旋转角度
            // 计算水平旋转角度
            float deltaHorizontal = speedHorizontal * deltaMousePosition.x;
            var newHorizontal = currentHorizontal - deltaHorizontal;
            //newHorizontal = Mathf.SmoothDamp(currentHorizontal, newHorizontal,ref velocityX, Time.unscaledDeltaTime);
            // 更新摄像机跟随脚本的旋转角度
            cameraFollow.polarDeg = newHorizontal;

            //Debug.Log("cameraFollow.polarDeg" + cameraFollow.polarDeg);

            currentHorizontal = newHorizontal;
            float deltaVertical = speedVertical * deltaMousePosition.y;
            var newVertical = currentVertical - deltaVertical;
            //newHorizontal = Mathf.SmoothDamp(currentVertical, newVertical, ref velocityY, Time.unscaledDeltaTime);
            // 更新摄像机跟随脚本的旋转角度
            cameraFollow.elevationDeg = Mathf.Clamp(newVertical, -90f, 89);
            currentVertical = newVertical;

            lastMousePosition = Input.mousePosition;
        }
        else {

        }
    }









}

到了这里,关于Unity组件开发--相机跟随角色和旋转的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity【角色/摄像机移动控制】【3.摄像机跟随角色】

    本章代码基于前两章。 1. 我们新建CameraController脚本,将其挂载到Camera上 2. 在角色Player下新建一个空物体,命名为cameraTargetPoint,并将该物体挂载至CameraController脚本中【注意代码中的这行:public Transform cameraTargetPoint;】,将该空物体放在人物头部附近位置 3.将PlayerController脚本

    2024年02月22日
    浏览(52)
  • Unity 旋转跟随

    效果: 主要用于在编辑器中可视化对象的朝向,同时提供了选择不同轴向的功能。在运行时,物体将根据所选择的轴向朝向目标,并在 Scene 视图中绘制一个带箭头的圆环。 定义轴向枚举: 这是一个用于表示轴向的枚举,包括 x 轴、y 轴和 z 轴。 定义变量: target: 用于指定需

    2024年01月18日
    浏览(60)
  • unity摄像机跟随鼠标旋转

     float vertical = Input.GetAxis(\\\"Mouse X\\\") float horizontal = Input.GetAxis(\\\"Mouse Y\\\") 第二种 通过 计算坐标时只需要通过 Quaternion.Euler 来取得旋转四元数,以玩家为原点衍生一条(0,0,-1)的向量并乘上四元数以旋转至 Player 指向摄像机的方向,最后乘上 Distance ,即可得到摄像机相对玩家的偏移

    2024年02月11日
    浏览(68)
  • unity相机跟随和相机边界(Cinemachine)

    1.在 Unity 编辑器中打开 Package Manager(菜单:Window Package Manager) 2.找到 Cinemachine 条目,然后单击右下角的 Install。 1.要开始使用 Cinemachine,你需要在顶部菜单栏上选择 Cinemachine Create 2D Camera 条目,从而将 Cinemachine 2D 摄像机添加到场景中。 2.此时将创建一个名为 CM vcam1 的新游戏

    2024年02月11日
    浏览(64)
  • [游戏开发][Unity] TPS射击游戏相机实现

    滑屏控制 角色的横向旋转 相机的纵向旋转(区别于横向旋转) 相机贴墙拉近(不能穿墙) 相机观察旋转(角色不转相机转用于观察四周) 开火按钮和旋转屏幕功能共存(边开枪边转向瞄准) 市面上的TPS射击游戏基本上有两种实现射击瞄准 方案一:以枪口射击方向为基准,相机跟着人

    2024年02月16日
    浏览(39)
  • 【Unity】实现相机跟随及视角转动

    【unity】实现相机跟随,人物移动请参照【Unity】 实现角色移动、视角旋转以及跳跃 1.创建一个 Camera ,将 Camera 置于物体 Player 下 随意拖动 Camera 到合适的位置 具体参数【仅供参考】 运行效果如下 1.创建两个空物体 CameraHandle 和 Pivot ,将相机拖动到Pivot下,具体如图所示 其中

    2023年04月27日
    浏览(50)
  • 【Unity-Cinemachine相机】相机跟随之Transposer属性

    上面的偏移量就是Follow Offset Binding Mode决定Follow Offset是目标本地坐标系下的身后十米还是世界坐标系下的身后十米 Lock To Target On Assign:锁定自己和目标本地坐标系的距离,朝向和目标本地坐标系方向相同 World Space:此时的坐标指的是世界坐标系下的坐标而不是Follow目标本地坐

    2024年02月09日
    浏览(46)
  • 【Unity】常见的角色移动旋转

      在Unity 3D游戏引擎中,可以使用不同的方式对物体进行旋转。以下是几种常见的旋转方式: 欧拉角(Euler Angles) :欧拉角是一种常用的旋转表示方法,通过绕物体的 X、Y 和 Z 轴的旋转角度来描述物体的旋转。在Unity中,可以通过修改物体的 transform.eulerAngles 属性来进行欧拉

    2024年02月10日
    浏览(45)
  • unity--相机跟随与屏幕自适应的实现

    如何让相机跟着人物跑呢?这是个不太大但是需要解决的问题。 思路就是用LateUpade(保证在所有更新函数都调用完调用)实时监测相机的位置,让他一直和游戏主角保持一定的距离。 开始执行: 创建个脚本给相机绑上 然后我们开始写里面的代码。 写代码 把参数设置下 完成

    2024年02月15日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包