Unity 算法功能 日記
来源:互联网 发布:好用的会计软件 编辑:程序博客网 时间:2024/05/29 14:33
Hello ,I am KitStar
1. 相机根据玩家与玩家位置 进行智能跟随 方法
在使用相机跟随玩家对象的时候。往往会使用多种模式进行。本文将介绍两种方式。
其实,就是就是transform.LookAt 不同参数的效果。
但是,都是可以根据玩家与敌人的距离进行相应的 高度,距离变化的。
由于比较简单,所以直接老规矩上脚本吧。
using UnityEngine;public class FollowCamera : MyMonoSingleton<FollowCamera>{ public enum CamerMotionMode { FollowOnly, // 只跟随 Trailing //尾随,会根据玩家旋转进行旋转 } public CamerMotionMode camerMotionMode = CamerMotionMode.FollowOnly; [Tooltip("玩家对象")] public Transform SelfTarget; [Tooltip("敌人对象")] public Transform EnemyTarget; [Tooltip("只用于观察")] public float spaceBetween = 0; //敌人与自己之间的距离 public float Distance = 10f; //后方距离 public float Height = 5f; //高度 public float smooth = 2f; // 插值系数 private Vector3 tagerPosition; // 目标位置 void Awake() { if (Instance != null) Debug.LogError("Instance FollowCamera x2"); else { Instance = this; } } float dis_register = 0; //寄存距离值 float height_register = 0; //寄存高度值 void LateUpdate() { //根据双方距离调节相机高度以及距离 if(EnemyTarget != null) // 如果存在敌人。则时刻对自己与敌人的距离进行一个插值 { dis_register = Vector3.Distance(SelfTarget.position, EnemyTarget.transform.position); spaceBetween = Mathf.Lerp(spaceBetween, dis_register, Time.deltaTime); } else // 如果不存在敌人,则缓慢的从新回到最初高度。 { if(spaceBetween > 0 ) { spaceBetween = Mathf.Lerp(spaceBetween, 0, Time.deltaTime); } else { spaceBetween = 0; } } height_register = Height + (spaceBetween / 4); // 得到最终高度 float currentHeight = Mathf.Lerp(transform.position.y, SelfTarget.position.y + height_register, smooth * Time.deltaTime); // 对高度进行插值计算。防止出现摄像机位置突然变化 if(camerMotionMode == CamerMotionMode.FollowOnly) { // 和下面逻辑一下。 transform.position = SelfTarget.position; // 得到玩家位置 transform.position -= Vector3.forward * (Distance + (spaceBetween / 1.5f)); // 向玩家位置后方移动 transform.position = new Vector3(transform.position.x, currentHeight, transform.position.z); // 向上方移动 transform.LookAt(SelfTarget.position); // 只看向位置 } else { /* 下面的代码和上面的代码 效果差不多。逻辑都是一样的。 得到,玩家位置向后以及向上的 一个 向量。然后对让相机去这个向量的位置。 但是如果,使用下面这个方式 就要对smooth 进行加大,不然,两次插值计算,得到的运动会很慢。或者读者改其他方式,因为这里我不用这个方法所以不多做改动了。哈哈哈 ~ ~ ~ ~ */ tagerPosition = SelfTarget.position + Vector3.up * currentHeight - SelfTarget.forward * (Distance + (spaceBetween / 1.5f)); transform.position = Vector3.Lerp(transform.position, tagerPosition, Time.deltaTime * smooth); transform.LookAt(SelfTarget); // 看向位置和更具旋转进行相应变化 } } public void SetTarget(Transform target) { SelfTarget = target; } public void SetParame(float dis, float height, float heightDamp) { Distance = dis; Height = height; smooth = heightDamp; }}
2. 对象平滑跟随目标
咱还是直接代码吧.官方案例
using UnityEngine;public class SmoothFollow : MonoBehaviour { // The target we are following [SerializeField] private Transform target; // The distance in the x-z plane to the target [SerializeField] private float distance = 10.0f; // the height we want the camera to be above the target [SerializeField] private float height = 5.0f; [SerializeField] private float rotationDamping; [SerializeField] private float heightDamping; // Use this for initialization void Start() { } // Update is called once per frame void LateUpdate() { // Early out if we don't have a target if (!target) return; // Calculate the current rotation angles var wantedRotationAngle = target.eulerAngles.y; var wantedHeight = target.position.y + height; var currentRotationAngle = transform.eulerAngles.y; var currentHeight = transform.position.y; // Damp the rotation around the y-axis currentRotationAngle = Mathf.LerpAngle(currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime); // Damp the height currentHeight = Mathf.Lerp(currentHeight, wantedHeight, heightDamping * Time.deltaTime); // Convert the angle into a rotation var currentRotation = Quaternion.Euler(0, currentRotationAngle, 0); // Set the position of the camera on the x-z plane to: // distance meters behind the target transform.position = target.position; transform.position -= currentRotation * Vector3.forward * distance; // Set the height of the camera transform.position = new Vector3(transform.position.x ,currentHeight , transform.position.z); // Always look at the target transform.LookAt(target); } }
3. 确定一个对象是否在这个对象的锥形范围之内。可以不使用碰撞或者粒子检测
咱还是直接代码吧.
public class GameAlgorithm{ public static bool JudgmentRoundRange(Transform self , Transform tager, float high = 1, float wide = 1,float distance = 100) { if (Vector3.Distance(self.position, tager.position) > distance || Vector3.Dot(self.position, (tager.position - self.position)) < 0) // 距离 范围内部 { Debug.Log("car of distances : Ok"); return false; } else { Debug.Log("two of distances : Ok"); Vector3 shootdir = (tager.position - self.position).normalized; // 射击的方向 Vector3 right = self.transform.right; // 玩家 右边 Vector3 forward = self.transform.forward; // 玩家 前面 Vector3 up = self.transform.up; //玩家 下面 //算出在xoz方向上的投影 Vector3 dirRight = Vector3.Cross(Vector3.Cross(up, shootdir).normalized, up).normalized; //yoz方向上的投影 Vector3 dirUp = Vector3.Cross(Vector3.Cross(right, shootdir).normalized, right).normalized; //左右cos,递减区间(-60,60):(>=) bool condition3 = Vector3.Dot(forward, dirRight) >= Mathf.Cos(35 * Mathf.Deg2Rad); // 大于 20 度的 弧 //上下cos(-45,45) return condition3 && Vector3.Dot(forward, dirUp) >= Mathf.Cos(35 * Mathf.Deg2Rad); } }}
4. 获取网络时间(用户软件的限时操作,或者需要网络时间的操作)
哭笑,还是直接代码吧.
public class NetWorkManage : MonoBehaviour { private float timeStamp; // private string timeStamp_Str; private StringBuilder timeStamp_Str = new StringBuilder(25, 30); Double timerStr; DateTime time = DateTime.MinValue; DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); public void Awake() { StartCoroutine(GetTimeStamp()); //开始 获取网络时间 } // 获取一次网络时间之后,让时间自己进行累加。不需要重复获取。 private void FixedUpdate() { timerStr += Time.deltaTime * 1000; time = startTime.AddMilliseconds(timerStr); timeStamp_Str.Remove(0, timeStamp_Str.Length); timeStamp_Str.Append(time.ToString()); timeStamp_Str.Append("\n"); timeStamp_Str.Append(time.Millisecond.ToString()); // timeStamp_Str = time.ToString(); timeStamp = time.Millisecond; } #region 网络时间 /// <summary> /// 获取 时间的 当前 秒 /// </summary> public int GetGameTimeSecond { get { return time.Second; } } /// <summary> /// 获取当前时间戳 /// </summary> public float GetGameTimeStamp { get { return timeStamp; } } /// <summary> /// 获取当前时间,以及当前毫秒数值 /// </summary> public string GetGameTimeStampStr { get { if (timeStamp_Str != null) { return timeStamp_Str.ToString(); } else { return null; } } } float waitTime = 1; private IEnumerator GetTimeStamp() { WWW www = new WWW("http://www.hko.gov.hk/cgi-bin/gts/time5a.pr?a=1"); yield return www; try { if(!Double.TryParse(www.text.Substring(2),out timerStr)) { StartCoroutine(GetTimeStamp()); } } catch (Exception e) { PublicClass.Log("NetWork error : " + e); } yield return new WaitForSeconds(waitTime); // 防止 时间有偏差,刚开始会快速更新。后面十秒间隔更新一次 waitTime++; waitTime = Mathf.Min(waitTime,10); StartCoroutine(GetTimeStamp()); } #endregion 网络时间 }
5.第三人称的人物摄像头控制,中间控制远近,右键滑动控制旋转,如果检测到障碍物,自己调节相机远近距离
咱还是直接代码吧
using UnityEngine; using System.Collections; public class PlayerCamera : MonoBehaviour { public Transform target; public float attackTimer; public float targetHeight = 1.7f; public float distance = 5.0f; public float offsetFromWall = 0.1f; public float maxDistance = 20; public float minDistance = .6f; public float xSpeed = 200.0f; public float ySpeed = 200.0f; public int yMinLimit = -80; public int yMaxLimit = 80; public int zoomRate = 40; public float rotationDampening = 3.0f; public float zoomDampening = 5.0f; public LayerMask collisionLayers = -1; private float xDeg = -53.2f; private float yDeg = 22.4f; private float currentDistance; private float desiredDistance; private float correctedDistance; void Start () { attackTimer=0.05f; currentDistance = distance; desiredDistance = distance; correctedDistance = distance; if (GetComponent<Rigidbody>()) GetComponent<Rigidbody>().freezeRotation = true; } void LateUpdate () { if(attackTimer>0) attackTimer-=Time.deltaTime; if(attackTimer<0) attackTimer=0; if(attackTimer==0){ target = GameObject.FindGameObjectWithTag("Player").transform; } Vector3 vTargetOffset; if (!target){ return; } if (Input.GetMouseButton(1) ) { xDeg += Input.GetAxis ("Mouse X") * xSpeed * 0.02f; yDeg -= Input.GetAxis ("Mouse Y") * ySpeed * 0.02f; } yDeg = ClampAngle (yDeg, yMinLimit, yMaxLimit); xDeg = ClampAngle (xDeg, -360, 360); Quaternion rotation = Quaternion.Euler (yDeg, xDeg, 0); desiredDistance -= Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs (desiredDistance); desiredDistance = Mathf.Clamp (desiredDistance, minDistance, maxDistance); correctedDistance = desiredDistance; vTargetOffset = new Vector3 (0, -targetHeight, 0); Vector3 position = target.position - (rotation * Vector3.forward * desiredDistance + vTargetOffset); RaycastHit collisionHit; Vector3 trueTargetPosition = new Vector3 (target.position.x, target.position.y + targetHeight, target.position.z); bool isCorrected = false; if (Physics.Linecast (trueTargetPosition, position, out collisionHit, collisionLayers.value)) { correctedDistance = Vector3.Distance (trueTargetPosition, collisionHit.point) - offsetFromWall; isCorrected = true; } currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * zoomDampening) : correctedDistance; currentDistance = Mathf.Clamp (currentDistance, minDistance, maxDistance); position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset); transform.rotation = rotation; transform.position = position; } private static float ClampAngle (float angle, float min, float max) { if (angle < -360) angle += 360; if (angle > 360) angle -= 360; return Mathf.Clamp (angle, min, max); } }
6. 在游戏运行的时候,往往需要 在 正交Orthographic (无消失点投影)
与透视Perspective (有消失点投影)
两个视角中来回转化。 以达到 不同的 2D 与 3D 视角。
So! 今天的 实例代码就是 描述了 这一个功能:
using UnityEngine;public enum Views{ _2DView = 1, _3DView} public class BackupCameraProjectionChange { /// <summary> /// 相机透视改变是否触发(调用只需把此值改为true) /// </summary> public bool ChangeProjection = false; private bool _changing = false; private float ProjectionChangeTime = 0.5f; private float _currentT = 0.0f; private Camera m_Camera;protected Views cur_Views = Views._3DView;public Views GetCurViews{ get { return cur_Views; }}public BackupCameraProjectionChange(Camera camera = null , float speed = 0.5f){ ProjectionChangeTime = speed; if (m_Camera == null && camera == null) { m_Camera = Camera.main; } else { m_Camera = camera; }}///这个 Update 需要在 其他继承自 MonoBehaviour 类的 Update 中 调用public void Update(){ if (m_Camera == null) return; if (_changing) { ChangeProjection = false; } else if (ChangeProjection) { _changing = true; _currentT = 0.0f; } LateUpdate();}void LateUpdate(){ if (!_changing) { return; } //将当前的 是否正视图值 赋值给currentlyOrthographic变量 bool currentlyOrthographic = m_Camera.orthographic; //定义变量存放当前摄像机的透视和正视矩阵信息; Matrix4x4 orthoMat, persMat; if (currentlyOrthographic)//如果当前摄像机为正视状态,则切换为3D { orthoMat = m_Camera.projectionMatrix; //保留 2D矩阵信息 m_Camera.orthographic = false; //为 3D m_Camera.ResetProjectionMatrix(); persMat = m_Camera.projectionMatrix; //保留 3D 矩阵信息 cur_Views = Views._3DView; } else//否则当前摄像机为透视状态, 则切换为2D { persMat = m_Camera.projectionMatrix; //保留 3D 矩阵信息 m_Camera.orthographic = true; //为2D m_Camera.ResetProjectionMatrix(); orthoMat = m_Camera.projectionMatrix; //保留 2D矩阵信息 cur_Views = Views._2DView; } m_Camera.orthographic = currentlyOrthographic; _currentT += (Time.deltaTime / ProjectionChangeTime); if (_currentT < 1.0f) { if (currentlyOrthographic) { m_Camera.projectionMatrix = MatrixLerp(orthoMat, persMat, _currentT * _currentT); //从2D 到 3D } else { m_Camera.projectionMatrix = MatrixLerp(persMat, orthoMat, Mathf.Sqrt(_currentT)); //从3D 到 2D } } else { _changing = false; m_Camera.orthographic = !currentlyOrthographic; //取反 m_Camera.ResetProjectionMatrix(); // 重置 }}private Matrix4x4 MatrixLerp(Matrix4x4 from, Matrix4x4 to, float t){ t = Mathf.Clamp(t, 0.0f, 1.0f); Matrix4x4 newMatrix = new Matrix4x4(); newMatrix.SetRow(0, Vector4.Lerp(from.GetRow(0), to.GetRow(0), t)); newMatrix.SetRow(1, Vector4.Lerp(from.GetRow(1), to.GetRow(1), t)); newMatrix.SetRow(2, Vector4.Lerp(from.GetRow(2), to.GetRow(2), t)); newMatrix.SetRow(3, Vector4.Lerp(from.GetRow(3), to.GetRow(3), t)); return newMatrix;}}
阅读全文
1 0
- Unity 算法功能 日記
- Unity的网络功能
- Unity-- 一些功能转载
- [unity3d]unity聊天功能
- [unity3d]unity聊天功能
- unity的网络功能
- Unity陀螺仪功能
- unity角色选择功能
- Unity的网络功能
- Unity的优化功能
- Unity-- 一些功能转载
- Unity的拍照功能
- Unity换装功能
- Unity发送邮件功能
- Unity实现弹幕功能
- unity实现录音功能
- Unity生成二维码功能
- Unity对象旋转功能
- android判断应用是否已经启动
- JDFZD2总结
- 2729:Blah数集(3.4数据结构之队列)
- numpy中矩阵合并
- nginx + php5.6 + mongo3.2配置安装php mongo扩展
- Unity 算法功能 日記
- 最长回文字串(JAVA实现)
- 找不到或无法加载主类
- NYOJ 中缀式变成后缀式(栈)
- python取数作为临时极大值(极小值)
- hdu1598贪心+并查集的巧妙用法
- centos7 下因/etc/rc.d/rc.local文件出错导致系统起不来
- 剑指offer——二叉树的镜像
- Linux命令详解