diff --git a/posts/studycase2.md b/posts/studycase2.md index 47d1980..082e91e 100644 --- a/posts/studycase2.md +++ b/posts/studycase2.md @@ -34,7 +34,7 @@ head: ## 4.初始祭坛-前置准备 -### 1. 导入[FBX模型](/resources/studycase2/FBX.zip),导入[shader](/resources/studycase2/SimpleURPToon.zip) +### 导入[FBX模型](/resources/studycase2/FBX.zip),导入[shader](/resources/studycase2/SimpleURPToon.zip) - 新健文件夹导入FBX @@ -114,7 +114,7 @@ head: ### 编写脚本`ThirdCharacterController.cs` -- 修改`Assets\Scripts\StudyCase2` 下脚本 `ThirdCharacterController` +- 修改`Assets\Scripts\StudyCase2` 下脚本 `ThirdCharacterController.cs` ```csharp using UnityEngine; using UnityEngine.InputSystem; diff --git a/posts/studycase3.md b/posts/studycase3.md new file mode 100644 index 0000000..3ce1e7d --- /dev/null +++ b/posts/studycase3.md @@ -0,0 +1,285 @@ +--- +title: StudyCase3 +date: 2025-11-26 21:33 +tags: [studycase, unity] +pinned: true +head: + - - meta + - name: description + content: vitepress-theme-bluearchive StudyCase3 + - - meta + - name: keywords + content: vitepress theme bluearchive StudyCase3 +--- + +# 物体拾取 + - [世界构筑的起始篇章-编辑器](#_1-世界构筑的起始篇章-编辑器) + - [光芒汇聚之所-章节目标](#_2-光芒汇聚之所-章节目标) + - [光流影卷-演示视频](#_3-光流影卷-演示视频) + - [初始祭坛-前置准备](#_4-初始祭坛-前置准备) + - [勇者行迹录-章节任务](#_5-勇者行迹录-章节任务) + - [异闻录-FAQ](#_6-异闻录-faq) + +## 1.世界构筑的起始篇章-编辑器 +- **Unity 2022.3.62f2**: +- **Visual Studio 2022** + +## 2.光芒汇聚之所-章节目标 +- **射线检测拾取物体** +- **鼠标点击拾取物体** + +## 3.光流影卷-演示视频 + + +## 4.初始祭坛-前置准备 +### 导入[资源](/resources/studycase3/case3.unitypackage)(天空球,描边,道具模型) + +## 5.勇者行迹录-章节任务 +### 创建StudyCase3 +- 复制场景和脚本改名为StudyCase3 +- 修改控制器的命名空间 + +### 道具 +- 把导入的道具模型放到场景中 + + + +- 新建道具层级 + + + +- 在`Assets\Scripts\StudyCase3`下创建道具脚本`Item.cs` +```csharp +using UnityEngine; + +namespace StudyCase3 +{ + public class Item : MonoBehaviour + { + Outline outline; + bool pick; + ThirdCharacterController player; + private void Awake() + { + player = FindAnyObjectByType(); + if (outline == null) + outline = gameObject.AddComponent(); + else + outline = GetComponent(); + outline.enabled = false; + outline.OutlineMode = Outline.Mode.OutlineVisible; + outline.OutlineColor = new Color(0, 1, 1); + outline.OutlineWidth = 10f; + gameObject.layer = LayerMask.NameToLayer("Item"); + } + public void Select() + { + if(!pick) + outline.enabled = true; + } + public void UnSelect() + { + if (!pick) + outline.enabled = false; + } + public void PickUp(Transform root) + { + if (pick) return; + pick = true; + transform.SetParent(root); + outline.OutlineWidth = 2f; + gameObject.layer = LayerMask.NameToLayer("Default"); + player.SetItems(); + } + private void OnMouseEnter() + { + if (player.pickMode == PickMode.Mouse) + Select(); + } + private void OnMouseExit() + { + if (player.pickMode == PickMode.Mouse) + UnSelect(); + } + private void OnMouseDown() + { + if (player.pickMode == PickMode.Mouse) + PickUp(player.itemRoot); + } + } +} +``` +- 道具挂载脚本 + + + +- 修改`Assets\Scripts\StudyCase3` 下脚本 `ThirdCharacterController.cs` +```csharp +using UnityEngine; +using UnityEngine.InputSystem; + +namespace StudyCase3 +{ + public enum PickMode + { + RayCast, + Mouse + } + public class ThirdCharacterController : MonoBehaviour + { + [Header("MoveSettings")] + CharacterController characterController; + InputActionAsset inputAction; + Animator animator; + Transform forward; + Transform model; + Cinemachine.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 Transform itemRoot; + Item selectItem; + LineRenderer lineRenderer; + private void Awake() + { + Cursor.lockState = cursorLock; + characterController = GetComponent(); + forward = transform.Find("Forward"); + model = transform.Find("Model"); + animator = model.GetComponentInChildren(); + vCam = transform.Find("Virtual Camera").GetComponent(); + inputAction = Resources.Load("Player"); + 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.Enable(); + itemRoot = transform.Find("ItemRoot"); + } + private void Update() + { + Move(); + CheckRayHit(); + ItemsRotate(); + } + public void OnMove(InputAction.CallbackContext context) + { + if (characterController.isGrounded) + moveInput = context.ReadValue(); + else moveInput = Vector2.zero; + } + public void OnJump(InputAction.CallbackContext context) + { + if (context.performed && characterController.isGrounded) + { + moveDir.y = jumpSpeed; + } + } + 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() + { + if (pickMode != PickMode.RayCast) 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(); + 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) + { + if (lineRenderer == null) + { + lineRenderer = gameObject.AddComponent(); + lineRenderer.material = new Material(Shader.Find("Universal Render Pipeline/2D/Sprite-Unlit-Default")); + lineRenderer.useWorldSpace = true; + } + if (!useDrawRay) + { + lineRenderer.enabled = false; + return; + } + 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 + } +} +``` +- 玩家挂载脚本,创建ItemRoot节点,设置射线检测层级 + + + +## 6.异闻录-FAQ \ No newline at end of file diff --git a/public/image/studycase3/把导入的道具模型放到场景中.png b/public/image/studycase3/把导入的道具模型放到场景中.png new file mode 100644 index 0000000..5aac55a Binary files /dev/null and b/public/image/studycase3/把导入的道具模型放到场景中.png differ diff --git a/public/image/studycase3/新建Layer.png b/public/image/studycase3/新建Layer.png new file mode 100644 index 0000000..e39ed67 Binary files /dev/null and b/public/image/studycase3/新建Layer.png differ diff --git a/public/image/studycase3/玩家挂载脚本,创建ItemRoot节点,设置射线检测层级.png b/public/image/studycase3/玩家挂载脚本,创建ItemRoot节点,设置射线检测层级.png new file mode 100644 index 0000000..230c45f Binary files /dev/null and b/public/image/studycase3/玩家挂载脚本,创建ItemRoot节点,设置射线检测层级.png differ diff --git a/public/image/studycase3/道具挂载脚本.png b/public/image/studycase3/道具挂载脚本.png new file mode 100644 index 0000000..3a546d5 Binary files /dev/null and b/public/image/studycase3/道具挂载脚本.png differ diff --git a/public/resources/studycase3/case3.unitypackage b/public/resources/studycase3/case3.unitypackage new file mode 100644 index 0000000..b848ee8 Binary files /dev/null and b/public/resources/studycase3/case3.unitypackage differ diff --git a/public/video/studycase3/演示视频.mp4 b/public/video/studycase3/演示视频.mp4 new file mode 100644 index 0000000..433ed18 Binary files /dev/null and b/public/video/studycase3/演示视频.mp4 differ diff --git a/public/video/studycase3/演示视频.png b/public/video/studycase3/演示视频.png new file mode 100644 index 0000000..b59b261 Binary files /dev/null and b/public/video/studycase3/演示视频.png differ