【原】3D游戏中的算法--MMO游戏全视角3D相机,全地形中视觉障碍物自动缩进调整

更新时间:2023-06-17 11:22:44 阅读: 评论:0

【原】3D游戏中的算法--MMO游戏全视⾓3D相机,全地形中视觉障
碍物⾃动缩进调整
⼤家好,欢迎⼤家多多交流,转载请注明出处,谢谢。
我来博客园的第⼀篇博客,想写的东西很多,基于⽬前⼯作⼿⾥的内容,先上⼀篇算法的。
上周做了个3D⾃由相机功能,需要对地形和墙壁进⾏⾃动缩进动画,效果经过多款游戏对⽐,决定编写《万王之王》的相机效果。
我发现很多同学,基础知识都不错,但是⾃⼰写的话,却不知道怎么去实现具体算法和⽅案,其实这种情况不⽤着急,养成好的需求分析习惯会帮助你提前解决很多难题。但是需求分析再好,对于算法来说,基础知识的掌握更加重要。
所以下⾯⼏个步骤是解决问题的流程。
第⼀步:⾸先就是⾃⾝基础了,关于3d向量的掌握,必须达到⼀定层次,否则很难处理好这种复杂环境下的算法策略,如果算法不好的,接着看,或许能让你有所提⾼。
第⼆步:其次就是对于相机功能的需求分析,需求分析是通过游戏还有和游戏策划沟通的结果,需求分析的准确与否决定了我们最终的结果,否则需求分析的错误或者不明确会带来代码策略的错误,影响⼯期。
第三步:很多同学到这⾥可能以为要开始动⼿写代码了,不着急,这⾥建议⼤家先整理游戏中相关流程,确定⾃⼰⽅案可⾏性,然后编写伪代码或者⽅案流程。伪代码能提前实验逻辑的可⾏性和纰漏,总览全局,避免实际编写代码过程中的盲⽬或者⽚⾯引起的时间成本。
第四步:接下来可以开始编写你的代码了。
相机涉及数学知识:
涉及的数学知识不多,作为游戏开发⼈员,这些知识点事必备技能,如果有不熟悉或者不知道的,⼀定要及时补充知识。
1:主要是对3d空间的理解,空间点,空间向量,空间⾓度的概念。
2:熟悉3D向量相关计算,余弦公式,⾓度计算,三⾓函数,向量投影计算和物理意义
3:熟悉笛卡尔坐标系,熟悉点乘积和叉乘积计算和物理意思,知道右⼿定则,平⾯法线等知识。
相机需求:
1:3D⾃由相机通⽤功能,滑动屏幕可以随意调整⽅向和缩进显⽰距离。
2:在1基础上对相机进⾏遮挡碰撞处理,相机和⾓⾊中间有阻挡时相机⾃动越过障碍物(渐进运动⽅式),并且保持相机视域内不在物体内部(穿墙情况)。
3:相机离开遮挡的时候回复原来⾃由相机设置距离,并且动态回复到合适位置。
4:对任意形状的阻挡(墙⾯,地⾯,任意⾓度斜坡)进⾏处理后不穿强。
5:发⽣视觉遮挡时,缩进的速度与滑动屏幕的速度成正⽐(这样体验会好,慢慢转动相机,遇到视觉阻挡时,正常缩进动画,当快速滑动屏幕时,就需要快速缩进相机,以防⽌视线穿墙)
⽅案:
1:射线检测,因为需要考虑各种地形的⾓度,所以射线检测⽅案修改成,视椎体射线检测⽅案,请看函数NearClipPlanePoints。(相机视⼝的4个点分别向⽬标点打射线进⾏检测,碰撞点取距离⾓⾊最近的)
2:相机提前预检测,提前计算下⼀帧相机碰撞,再相机被遮挡实际发⽣前,进⾏预测。
3:相机终点调整,使⽤最优碰撞点进⾏调整,调整算法考虑到相机视⼝宽度,使相视⼝机完全避免边界与碰撞点穿插。
4:相机终点确认后,对相机进⾏平滑过渡动画的⽅式往⽬标点移动。
英语六级答案5:平滑过渡速率和触摸拖动⾓度变化速率成正⽐,防⽌滑动太⼤穿墙,也增加体验。
实现参考图:
如下图,椎体为四条碰撞检测射线:
穿墙后,相机进⾏调整以后的截图:
实现效果:参考万王之王,⼀样的效果。
代码实现:代码中关键步骤已经有注释,核⼼函数是CameraMovement。  1using UnityEngine;
2using System.Collections;
3using System.Collections.Generic;
4using Invector;
5using System;
6public class vThirdPersonCamera : MonoBehaviour
7 {
cdc是什么缩写
8public enum CameraState
9    {
10        Drag,
11        Auto,
12        AutoFixY,
13    }
14public static vThirdPersonCamera Create()
15    {
16var go = new GameObject("vThirdPersonCamera");
17        vThirdPersonCamera comp = go.AddComponent<vThirdPersonCamera>();
18        GameObject.DontDestroyOnLoad(go);
19return comp;
21#region inspector properties
22    [Tooltip("Lerp speed between Camera States")]
23public float smoothCameraRotation = 12f;
24public float smoothCameraRotationAuto = 1;
25private float m_currentCameraRotation;
26    [Tooltip("What layer will be culled")]
27public LayerMask cullingLayer = 1 << 0;//碰撞检测⽤的layer,请根据⾃⼰游戏进⾏设置。 28public float rightOfft = 0f;
29public float defaultDistance = 12.5f;
30public float height = 2f;
31private float defaultHeight = 2f;
32public float smoothFollow = 5f;
33public float cameraAutoRotationSensitivity = 3f;
34public float xMouSensitivity = 0.2f;//3f;
35public float yMouSensitivity = 0.2f;//3f;
36public float yMinLimit = -70;
37public float yMaxLimit = 80f;
38public const float MinDistance = 0f;
39public const float MaxDistance = 35;
40public float currentDistance = 0;
41public float zoomSensitivity = 0.05f;
42public Transform cameraTransform;
43//public Transform otherTargetTransform;//相机动画锁定⽬标Trans
44#endregion
45#region hide properties
46    [HideInInspector]
47public float offSetPlayerPivot;
48//[HideInInspector]
49    [HideInInspector]
50public Vector2 movementSpeed;
51private Vector3 currentPlayerPos;
52private Vector3 currentPlayerDirection;
53private Vector3 currentPlayerDirectionRight;
54private Transform targetLookAt;    //⽬标观察点
55private Transform nextTargetLookAt;//⽬标观察点
56private Vector3 currentTargetPos;
57private Vector3 lookPoint;
58private Vector3 nextLookPoint;
59private Vector3 current_cPos;
60private Vector3 desired_cPos;
61private Vector3 nextTargetCameraPos = ;
62private Vector3 nextCameraPos = ;
63private Camera _camera;
64private float distance = 0f;
65private float mouY = 0f;
66private float mouX = 0f;
67private float currentHeight;
68private float cullingDistance;
69//private float checkHeightRadius = 0.4f;
70private float clipPlaneMargin = 0f;
71private float forward = -1f;
72private float xMinLimit = -360f;
73private float xMaxLimit = 360f;
74private RaycastHit hitInfo;
75private float distanceTime = 0f;
76private float curSmoothFollow = 5f;
77private CameraState mState = CameraState.Drag;
78private float clipOfft = 1f;//相机视⼝区域射线检测区扩⼤
79public CameraState State
80    {
81get
82        {
83return mState;
84        }
85t
86        {
87if (value == mState)
88return;
89            mState = value;
90            UpdateState();
91        }
92    }
93#endregion
94#region相机基础功能函数区--------------------------------------------------------------------------------
95private void UpdateState()
96    {
97switch (mState)
98        {
99ca CameraState.Auto:
100                m_currentCameraRotation = smoothCameraRotationAuto;
101break;
102ca CameraState.AutoFixY:
103break;
104default:
105                m_currentCameraRotation = smoothCameraRotation;
106break;
107        }
108    }
109public float GetMouX()
111return mouX;
112    }
113public float GetMouY()
郑中基与阿sa114    {
115return mouY;
116    }
117public void SetRotateY(float targetX)
118    {
119        mouX = targetX;
120    }
121public void Relea()
122    {
123if (targetLookAt != null)
124        {
125            GameObject.Destroy(targetLookAt);
126            targetLookAt = null;
127        }
128if (nextTargetLookAt != null)
129        {
130            GameObject.Destroy(nextTargetLookAt);
131            nextTargetLookAt = null;
谷歌是什么
132        }
133    }
134public void Init()
135    {
136        cullingLayer = 1 << (int)PublicConst.E_Layer.Layer_Road;
137        currentTargetPos = new Vector3(currentPlayerPos.x, currentPlayerPos.y + offSetPlayerPivot, currentPlayerPos.z); 138if (targetLookAt == null)
139        {
140            targetLookAt = new GameObject("targetLookAt").transform;
141            GameObject.DontDestroyOnLoad(targetLookAt);
142        }
143if (nextTargetLookAt == null)
144        {
145            nextTargetLookAt = new GameObject("nextTargetLookAt").transform;
146            GameObject.DontDestroyOnLoad(nextTargetLookAt);
147        }
148        targetLookAt.position = currentTargetPos;
149        ation = Quaternion.Euler(mouY, mouX, 0);
150        nextTargetLookAt.position = currentTargetPos;
151        ation = Quaternion.Euler(mouY, mouX, 0);
152        defaultDistance = Mathf.Clamp(defaultDistance, MinDistance, MaxDistance);
153if (State == CameraState.AutoFixY)
154        {
155            currentDistance = distance = camera2DDistance;
156        }
157el
158        {
159            currentDistance = distance = defaultDistance;
160        }
161        currentHeight = height;
162        UpdateState();
dove是什么意思163    }
164public void SetCamera(Camera cam, Transform cameraRootTrans, int xRot, int yRot)
165    {
166        mouY = xRot;
167        mouX = yRot;
168        _camera = cam;
169        cameraTransform = cameraRootTrans;
170        Init();
171    }
172///<summary>
173///相机看向⾓⾊的⾼度值,⽬的是看向⼈脸
174/// 1:不同⾼度的⾓⾊,需要配置这个值
175/// 2:在坐骑上⾼度 = 坐骑坐垫⾼度 + ⾓⾊⾼度*0.5
176///</summary>
177///<param name="_height">⾼度(单位⽶)</param>
178public void SetHeight(float pHeight)
179    {
180if(pHeight <= 0)
181        {
182            LiteCommon.BLog.E("相机中⾓⾊⾼度设置错误!值<=0!");
183            height = defaultHeight;
184return;
185        }
186        height = pHeight;
187    }
188///<summary>
189///相机在lateUpdate中的持续更新
190///</summary>
191public void UpdatePosition()
192    {
193        CameraMovement();
194    }
195///<summary>
196///持续缩进相机距离(触控滑动交互)
197///</summary>
198///<param name="delta"></param>
199public void UpdateZoomFactor(float delta)
201        currentDistance -= delta * zoomSensitivity;
202        currentDistance = Mathf.Clamp(currentDistance, MinDistance, MaxDistance);
203    }
204///<summary>
205///持续旋转相机⾓度(触控滑动交互)
206///</summary>
207///<param name="delta"></param>
208public void UpdateRotate(Vector2 delta)
209    {
210        RotateCamera(delta.x, delta.y);
211    }
212///<summary>
213///设置相机到固定位置
214///</summary>
215///<param name="_fixedAngleX">⽔平⾓度</param>
216///<param name="_fixedAngleY">垂直⾓度</param>
217///<param name="distance">相机对⽬标位置距离</param>
218public void SetCameraPos(float _fixedAngleX, float _fixedAngleY, float distance)
219    {
220        mouX = _fixedAngleX;
marshal
221        mouY = _fixedAngleY;
222        currentDistance = distance;
223    }
224///<summary>
225///更新⾓⾊位置
226///</summary>
227///<param name="pos"></param>
228public void UpdateRolePosition(Vector3 pos)
229    {
230        currentPlayerPos = pos;
231if (isLookingToOtherTarget)
232        {
frequency是什么意思>domino harvey233if (!isAutoLookingTargetSmooth && otherlookTarget != null)
234            {
235//Debug.Log("---->UpdateRolePosition otherlookTarget!");
236                currentTargetPos = otherlookTarget.position;
237            }
238        }
239el
240        {
241            currentTargetPos = currentPlayerPos;
242        }
243    }
244///<summary>
245///跟新相机⽬标对象的⽅向
246///</summary>
247///<param name="directionForward"></param>
248public void UpdateRoleDirection(Vector3 directionForward)
249    {
250        currentPlayerDirection = directionForward;
251        currentPlayerDirectionRight = Vector3.Cross(directionForward, Vector3.up);
252    }
253///<summary>
254/// Camera Update 实时刷新相机⽅位,并且避免碰撞
255///</summary>
256void CameraMovement()
257    {
258if (_camera == null)
259return;
260//next position and direction
is anyone up
261//distance = Mathf.Lerp(distance, currentDistance, smoothFollow * Time.deltaTime);
262//cullingDistance = Mathf.Lerp(cullingDistance, distance, Time.deltaTime);
263var camDir = (forward * targetLookAt.forward);
264        camDir.Normalize();
265var targetPos = new Vector3(currentTargetPos.x, currentTargetPos.y + offSetPlayerPivot, currentTargetPos.z); 266        currentTargetPos = targetPos;
267//look direction
268        lookPoint = desired_cPos + targetLookAt.forward * 2f;
269        lookPoint += (targetLookAt.right * Vector3.Dot(camDir * (distance), targetLookAt.right));
270//t current real looking height p;osition
271        currentHeight = height;
referrals272        desired_cPos = targetPos + new Vector3(0, height, 0);
273        current_cPos = currentTargetPos + new Vector3(0, currentHeight, 0);
274//next look Target
275        nextTargetLookAt.position = desired_cPos;
276        Quaternion newNextRot = Quaternion.Euler(mouY, mouX, 0);
277        ation = newNextRot;
278//next camera direction
279var nextCamDir = (forward * nextTargetLookAt.forward);
280        nextCamDir.Normalize();
281//next look direction
282        nextLookPoint = desired_cPos + nextTargetLookAt.forward * 2f;
283        nextLookPoint += (nextTargetLookAt.right * Vector3.Dot(nextCamDir * (currentDistance), nextTargetLookAt.right)); 284        nextCameraPos = desired_cPos + (nextCamDir * currentDistance);
285//calculate next ClipPlanePoints
286        ClipPlanePoints nextPlanePoints = _camera.NearClipPlanePoints(nextCameraPos, clipPlaneMargin, clipOfft); 287//if hit not success, then next target camera pos --> current camera pos
288//el calculate next target camera pos
289if (CullingRayCast(desired_cPos, nextPlanePoints, out hitInfo, currentDistance, cullingLayer, an))

本文发布于:2023-06-17 11:22:44,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/78/975150.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:游戏   代码   分析   需求
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图