Files
BA-VitePress-Pages/posts/studycase4.md
2025-12-01 19:00:28 +08:00

10 KiB
Raw Blame History

title, date, tags, pinned, head
title date tags pinned head
studycase4 2025-11-30 12:40:05
studycase
unity
true
meta
name content
description vitepress-theme-bluearchive studycase4
meta
name content
keywords vitepress theme bluearchive studycase4

虚拟摇杆

1.世界构筑的起始篇章-编辑器

  • Unity 2022.3.62f2
  • Visual Studio 2022

2.光芒汇聚之所-章节目标

  • 虚拟摇杆和按钮
  • In game Debug
  • 打包APK

3.光流影卷-演示视频

4.初始祭坛-前置准备

导入资源(摇杆图标、Debug工具)

导入InputSystem的OnScreen示例

5.勇者行迹录-章节任务

创建studycase4

  • 复制场景和脚本改名为studycase4
  • 修改控制器和道具的命名空间

IngameDebugConsole

  • 把IngameDebugConsole预制体拖入场景
  • 全选mobile-controls-1下的Texture
  • 切换到sprite(2d and ui)
  • 创建一个canvas再创建一个image命名为leftBgsprite使用joystick_circle_pad_a设置大小位置和锚点
  • 创建一个image命名为leftStick透明度0设置大小位置和锚点挂载On-Screen-Stick
  • 设置 MovementRange 为200设置 ControlPath 为LeftStick
  • 复制一个leftBg改名为rightBg设置大小位置和锚点
  • 复制一个leftStick改名为rightStick设置ControlPath 为RightStick
  • 添加输入事件Move添加LeftStick创建Look添加Detla和RightStick
  • 设置虚拟相机参数移动速度从300调到100限制角度0到70
  • 修改虚拟相机输入
  • 修改Assets\Scripts\studycase4 下脚本 ThirdCharacterController.cs
using UnityEngine;
using UnityEngine.InputSystem;
using Cinemachine;

namespace StudyCase4
{
    public enum PickMode
    {
        RayCast,
        Mouse
    }
    public class ThirdCharacterController : MonoBehaviour
    {
        [Header("MoveSettings")]
        CharacterController characterController;
        InputActionAsset inputAction;
        Animator animator;
        Transform forward;
        Transform model;
        CinemachineVirtualCamera vCam;
        public float moveSpeed = 5f;
        public float jumpSpeed = 2f;
        public float turnSpeed = 10f;
        public float gravity = 10f;
        Vector3 moveDir;
        Vector2 moveInput;
        [Header("PickSettings")]
        public PickMode pickMode = PickMode.RayCast;
        public CursorLockMode cursorLock;
        public bool useDrawRay = true;
        public float maxDistance = 5f;
        public LayerMask layerMask;
        public float itemsRotateSpeed = 120f;
        public float minCameraDistance = 2f;
        public float maxCameraDistance = 10f;
        public float cameraZoomSpeed = 0.1f;
        [HideInInspector] public Transform itemRoot;
        Item selectItem;
        LineRenderer lineRenderer;
        CinemachineFramingTransposer framingTransposer;
        private void Awake()
        {
            Cursor.lockState = cursorLock;
            characterController = GetComponent<CharacterController>();
            forward = transform.Find("Forward");
            model = transform.Find("Model");
            animator = model.GetComponentInChildren<Animator>();
            vCam = transform.Find("Virtual Camera").GetComponent<CinemachineVirtualCamera>();
            framingTransposer = vCam.GetCinemachineComponent<CinemachineFramingTransposer>();
            inputAction = Resources.Load<InputActionAsset>("PlayerInputActions");
            inputAction.FindAction("Move").started += OnMove;
            inputAction.FindAction("Move").performed += OnMove;
            inputAction.FindAction("Move").canceled += OnMove;
            inputAction.FindAction("Jump").performed += OnJump;
            inputAction.FindAction("Pick").performed += OnPickUp;
            inputAction.FindAction("Zoom").started += OnZoom;
            inputAction.FindAction("Zoom").performed += OnZoom;
            inputAction.FindAction("Zoom").canceled += OnZoom;
            inputAction.Enable();
            itemRoot = transform.Find("ItemRoot");
            if (lineRenderer == null)
            {
                lineRenderer = gameObject.AddComponent<LineRenderer>();
                lineRenderer.material = Resources.Load<Material>("Line");
                lineRenderer.useWorldSpace = true;
            }
            layerMask = LayerMask.GetMask("Item");
            //开启多点触控
            Input.multiTouchEnabled = true;
        }
        private void Update()
        {
            Move();
            CheckRayHit();
            ItemsRotate();
        }
        public void OnMove(InputAction.CallbackContext context)
        {
            if (characterController.isGrounded)
                moveInput = context.ReadValue<Vector2>();
            else moveInput = Vector2.zero;
        }
        public void OnJump(InputAction.CallbackContext context)
        {
            if (context.performed && characterController.isGrounded)
            {
                moveDir.y = jumpSpeed;
            }
        }
        //增加控制相机距离的方法
        public void OnZoom(InputAction.CallbackContext context)
        {
            float scrollValue = context.ReadValue<float>();
            float newDistance = framingTransposer.m_CameraDistance + (scrollValue * cameraZoomSpeed * 0.01f);
            framingTransposer.m_CameraDistance = Mathf.Clamp(newDistance, minCameraDistance, maxCameraDistance);
        }
        void Move()
        {
            moveDir = new Vector3(moveInput.x, moveDir.y, moveInput.y);
            forward.eulerAngles = new Vector3(0, vCam.transform.eulerAngles.y, 0);
            moveDir = forward.TransformDirection(moveDir);
            if (moveInput != Vector2.zero)
            {
                animator.SetBool("Move", true);
                Quaternion target = Quaternion.LookRotation(new Vector3(moveDir.x, 0, moveDir.z));
                model.rotation = Quaternion.Slerp(model.rotation, target, turnSpeed * Time.deltaTime);
            }
            else animator.SetBool("Move", false);
            if (!characterController.isGrounded)
                moveDir.y -= gravity * Time.deltaTime;
            characterController.Move(moveDir * moveSpeed * Time.deltaTime);
        }
        #region PickUp
        public void OnPickUp(InputAction.CallbackContext context)
        {
            if (pickMode != PickMode.RayCast) return;
            if (selectItem != null)
                selectItem.PickUp(itemRoot);
            selectItem = null;
        }
        void CheckRayHit()
        {
            lineRenderer.enabled = useDrawRay;
            if (pickMode != PickMode.RayCast) 
            {
                useDrawRay = false;
                return;
            }
            Ray ray = new Ray(model.position, model.forward);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, maxDistance, layerMask))
            {
                DrawRay(model.position, hit.point, new Color(0, 1, 1));
                Item curItem = hit.transform.GetComponent<Item>();
                if (curItem != null && curItem != selectItem)
                {
                    if (selectItem != null)
                        selectItem.UnSelect();
                    selectItem = curItem;
                    selectItem.Select();
                }
            }
            else
            {
                DrawRay(model.position, model.position+ model.forward* maxDistance, new Color(1, 1, 1));
                if (selectItem != null)
                    selectItem.UnSelect();
                selectItem = null;
            }
        }
        void DrawRay(Vector3 startPos, Vector3 endPos, Color color)
        {
            lineRenderer.startColor = lineRenderer.endColor = color;
            lineRenderer.startWidth = lineRenderer.endWidth = 0.1f;
            lineRenderer.positionCount = 2;
            lineRenderer.SetPosition(0, startPos);
            lineRenderer.SetPosition(1, endPos);
            lineRenderer.enabled = true;
        }
        void ItemsRotate()
        {
            itemRoot.Rotate(0,itemsRotateSpeed*Time.deltaTime, 0);
        }
        public void SetItems()
        {
            float radius = 1.5f;
            float angleStep = 360 / itemRoot.childCount;
            for (int i = 0; i < itemRoot.childCount; i++)
            {
                Transform item = itemRoot.GetChild(i);
                float angle = angleStep * i;
                Quaternion rot = Quaternion.Euler(0, angle, 0);
                item.localPosition = rot * itemRoot.forward * radius;
                item.localScale = Vector3.one * 0.1f;
            }
        }
        #endregion
    }
}
  • 玩家移除case3的脚本挂载case4脚本
  • BuildSettings切换到Android平台
  • 打包apk
  • 在手机上安装和运行

6.异闻录-FAQ