Unity LineRenderer 根据圆的中心、半径、朝向在三维空间中画圆

举报
CoderZ1010 发表于 2022/09/25 06:41:16 2022/09/25
【摘要】 在三维空间中生成一个圆,需要知道圆的中心点位置、圆的半径以及圆的朝向这三个参数,通过这三个参数求得在圆上的点坐标,最终通过LineRenderer组件将圆绘制出来: 首先从二维平面来看,我们已知圆的中心点(x0, y0),半径r,即可通过以下公式求得角度a的圆上的点坐标位置(x,y):    &nb...

在三维空间中生成一个圆,需要知道圆的中心点位置、圆的半径以及圆的朝向这三个参数,通过这三个参数求得在圆上的点坐标,最终通过LineRenderer组件将圆绘制出来:

首先从二维平面来看,我们已知圆的中心点(x0, y0),半径r,即可通过以下公式求得角度a的圆上的点坐标位置(x,y):

        x = x0 + r * cos(a * 3.14 / 180)

        y = y0 + r * sin(a * 3.14 / 180)

以Unity中的x轴、z轴形成的平面为例,假设我们每一度求得一个圆上的点坐标位置,通过360个坐标画出一个圆,代码如下:


  
  1. using UnityEngine;
  2. public class Example : MonoBehaviour
  3. {
  4. private void Start()
  5. {
  6. //圆的中心点位置
  7. Vector3 center = Vector3.zero;
  8. //圆的半径
  9. float radius = 3f;
  10. //添加LineRenderer组件
  11. LineRenderer lineRenderer = gameObject.AddComponent<LineRenderer>();
  12. //设置坐标点个数为360个
  13. lineRenderer.positionCount = 360;
  14. //将LineRenderer绘制线的宽度 即圆的宽度 设为0.04
  15. lineRenderer.startWidth = .04f;
  16. lineRenderer.endWidth = .04f;
  17. //每一度求得一个在圆上的坐标点
  18. for (int i = 0; i < 360; i++)
  19. {
  20. float x = center.x + radius * Mathf.Cos(i * Mathf.PI / 180f);
  21. float z = center.z + radius * Mathf.Sin(i * Mathf.PI / 180f);
  22. lineRenderer.SetPosition(i, new Vector3(x, 0, z));
  23. }
  24. }
  25. }

运行上面的代码,即可得到在x、z轴所在的平面上以原点为中心,3为半径的通过Line Renderer组件绘制出的一个圆,如图所示:

圆上缺了一个口,我们可以通过将Line Renderer组件的Loop属性设置为true来处理,该属性设为true后,可以将第一个点和最后一个点相连,形成闭环:

有了上述在二维平面上绘制圆的基础后,在三维空间中绘制一个圆,需要添加一个参数,即圆的朝向,可以通过一个坐标点的位置减去圆的中心的位置求得该方向向量。在x、z轴所在的平面绘制出的圆,其朝向即Vector3.up,我们可以通过Quaternion类中的FromToRotation函数将该方向旋转到我们指定的方向,再通过向量与四元数相乘求得圆上的坐标位置:


  
  1. using UnityEngine;
  2. public class Example : MonoBehaviour
  3. {
  4. //该点与圆的中心点形成一个圆的朝向
  5. [SerializeField] private Transform point;
  6. private void Start()
  7. {
  8. //圆的中心点位置 假设为(0, 0, 0)
  9. Vector3 center = Vector3.zero;
  10. //圆的半径
  11. float radius = 3f;
  12. //添加LineRenderer组件
  13. LineRenderer lineRenderer = gameObject.AddComponent<LineRenderer>();
  14. //设置坐标点个数为360个
  15. lineRenderer.positionCount = 360;
  16. //将LineRenderer绘制线的宽度 即圆的宽度 设为0.04
  17. lineRenderer.startWidth = .04f;
  18. lineRenderer.endWidth = .04f;
  19. //设置闭环
  20. lineRenderer.loop = true;
  21. //朝向
  22. Quaternion direction = Quaternion.FromToRotation(Vector3.up, point.position - Vector3.zero);
  23. //每一度求得一个在圆上的坐标点
  24. for (int i = 0; i < 360; i++)
  25. {
  26. float x = center.x + radius * Mathf.Cos(i * Mathf.PI / 180f);
  27. float z = center.z + radius * Mathf.Sin(i * Mathf.PI / 180f);
  28. Vector3 pos = new Vector3(x, 0, z);
  29. pos = direction * pos;
  30. lineRenderer.SetPosition(i, pos);
  31. }
  32. }
  33. }

我们将朝向在OnDrawGizmos函数中通过Handles类中的DrawLine方法绘制出来便于查看,该方法可以在Scene场景窗口中绘制出一条直线。关于OnDrawGizmos和Handles的介绍如下:


  
  1. private void OnDrawGizmos()
  2. {
  3. Handles.color = Color.cyan;
  4. Handles.DrawLine(Vector3.zero, point.position);
  5. }

到此,已经可以在三维空间中绘制出圆,最终我们通过this关键字将其封装到Line Renderer类中作为拓展方法:


  
  1. using UnityEngine;
  2. namespace SK.Framework
  3. {
  4. public static class LineRendererExtension
  5. {
  6. /// <summary>
  7. /// 绘制一个圆
  8. /// </summary>
  9. /// <param name="self">LineRenderer组件</param>
  10. /// <param name="center">圆的中心点坐标</param>
  11. /// <param name="direction">圆的朝向</param>
  12. /// <param name="radius">圆的半径</param>
  13. /// <param name="thickness">圆的宽度 即LineRenderer组件width</param>
  14. /// <returns></returns>
  15. public static LineRenderer DrawCircle(this LineRenderer self, Vector3 center, Vector3 direction, float radius, float thickness)
  16. {
  17. //设置宽度
  18. self.startWidth = thickness;
  19. self.endWidth = thickness;
  20. //设置坐标点个数
  21. self.positionCount = 360;
  22. //设置闭环
  23. self.loop = true;
  24. //朝向
  25. Quaternion q = Quaternion.FromToRotation(Vector3.up, direction);
  26. float x, z;
  27. //每一度求得一个在圆上的坐标点
  28. for (int i = 0; i < 360; i++)
  29. {
  30. x = center.x + radius * Mathf.Cos(i * Mathf.PI / 180f);
  31. z = center.z + radius * Mathf.Sin(i * Mathf.PI / 180f);
  32. Vector3 pos = new Vector3(x, center.y, z);
  33. pos = q * pos;
  34. self.SetPosition(i, pos);
  35. }
  36. return self;
  37. }
  38. }
  39. }

 测试代码:


  
  1. using UnityEngine;
  2. using UnityEditor;
  3. using SK.Framework;
  4. public class Example : MonoBehaviour
  5. {
  6. //圆的中心点
  7. [SerializeField] private Transform center;
  8. //该点与圆的中心点形成一个圆的朝向
  9. [SerializeField] private Transform point;
  10. private void OnDrawGizmos()
  11. {
  12. Handles.color = Color.cyan;
  13. Handles.DrawLine(center.position, point.position);
  14. }
  15. private void OnGUI()
  16. {
  17. if (GUILayout.Button("生成", GUILayout.Width(200f), GUILayout.Height(50f)))
  18. {
  19. LineRenderer line = gameObject.GetComponent<LineRenderer>();
  20. if (line == null) line = gameObject.AddComponent<LineRenderer>();
  21. line.DrawCircle(center.position, point.position - center.position, 3f, 0.04f);
  22. }
  23. }
  24. }

文章来源: coderz.blog.csdn.net,作者:CoderZ1010,版权归原作者所有,如需转载,请联系作者。

原文链接:coderz.blog.csdn.net/article/details/122971763

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。