【发布时间】:2012-12-04 17:19:15
【问题描述】:
如何在 Unity 3d 中画圆? 我想在不同的物体周围画一个圆圈。 圆的半径不同,圆有纹理——正方形。
【问题讨论】:
标签: unity3d
如何在 Unity 3d 中画圆? 我想在不同的物体周围画一个圆圈。 圆的半径不同,圆有纹理——正方形。
【问题讨论】:
标签: unity3d
我发现这段代码有一个很大的错误。点数(大小)不应为“(2 * pi / theta_scale) + 1”,因为这会导致圆绘制 6.28 次。大小应为“1 / theta_scale + 1”。所以对于 0.01 的 theta_scale 需要绘制 100 个点,对于 0.1 的 theta_scale 需要绘制 10 个点。否则它将分别绘制 62 次和 628 次。 这是我使用的代码。
using UnityEngine;
using System.Collections;
public class DrawRadar: MonoBehaviour {
public float ThetaScale = 0.01 f;
public float radius = 3 f;
private int Size;
private LineRenderer LineDrawer;
private float Theta = 0 f;
void Start() {
LineDrawer = GetComponent < LineRenderer > ();
}
void Update() {
Theta = 0 f;
Size = (int)((1 f / ThetaScale) + 1 f);
LineDrawer.SetVertexCount(Size);
for (int i = 0; i < Size; i++) {
Theta += (2.0 f * Mathf.PI * ThetaScale);
float x = radius * Mathf.Cos(Theta);
float y = radius * Mathf.Sin(Theta);
LineDrawer.SetPosition(i, new Vector3(x, y, 0));
}
}
}
如果修改“Size”中除以ThetaScale的数字,就可以制作出扫尺/饼图类型的图形。
【讨论】:
Size = (int)((1f / ThetaScale) + 2f)
SetVertexCount 现在已弃用。同样对于任何想知道他们的圈子在哪里的人,如果您没有关闭use world space,这会在世界原点创建一个垂直环。我为新版本的统一添加了答案。
See Unity Answers 类似问题。
float theta_scale = 0.1; // Circle resolution
LineRenderer lineRenderer = gameObject.AddComponent<LineRenderer>();
lineRenderer.material = new Material(Shader.Find("Particles/Additive"));
lineRenderer.SetColors(c1, c2);
lineRenderer.SetWidth(0.2F, 0.2F);
lineRenderer.SetVertexCount(size);
int i = 0;
for(float theta = 0; theta < 2 * PI; theta += theta_scale) {
x = r*cos(theta);
y = r*sin(theta);
Vector3 pos = new Vector3(x, y, 0);
lineRenderer.SetPosition(i, pos);
i+=1;
}
LineRenderer 需要连续点。您可以稍微修改此代码以使用圆柱体游戏对象而不是线渲染器。我发现 LineRenderer 有点可怕。
最后,类似于第一个链接,您可以将圆形纹理附加到单位平面。使不属于圆形的纹理的任何部分透明。然后只需缩放并对齐平面以适合您的对象。不幸的是,如果有人看起来几乎平行于平面,这种方法就不是很好。
【讨论】:
Jerdak 的解决方案很好,但是代码很乱,所以我不得不稍微调整一下。这是一个类的代码,我在循环中使用 i 来避免错误。
它还会用它的游戏对象位置更新圆的位置。
using UnityEngine;
using System.Collections;
public class CircleDraw : MonoBehaviour {
float theta_scale = 0.01f; //Set lower to add more points
int size; //Total number of points in circle
float radius = 3f;
LineRenderer lineRenderer;
void Awake () {
float sizeValue = (2.0f * Mathf.PI) / theta_scale;
size = (int)sizeValue;
size++;
lineRenderer = gameObject.AddComponent<LineRenderer>();
lineRenderer.material = new Material(Shader.Find("Particles/Additive"));
lineRenderer.SetWidth(0.02f, 0.02f); //thickness of line
lineRenderer.SetVertexCount(size);
}
void Update () {
Vector3 pos;
float theta = 0f;
for(int i = 0; i < size; i++){
theta += (2.0f * Mathf.PI * theta_scale);
float x = radius * Mathf.Cos(theta);
float y = radius * Mathf.Sin(theta);
x += gameObject.transform.position.x;
y += gameObject.transform.position.y;
pos = new Vector3(x, y, 0);
lineRenderer.SetPosition(i, pos);
}
}
}
【讨论】:
最佳答案中的 linerenderer 方法非常简单,正是我想要的。我针对较新版本的 Unity 进行了更新,并进行了一些小调整以使其对初学者/用户更加友好。
具体来说:
LineRenderer.SetVertexCount() 在较新版本的 Unity 中已弃用,替换为 positionCount
LineRenderer 的检查器中设置Update 函数 - 渲染的线条是一个持久的游戏对象using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class DrawRing : MonoBehaviour
{
public LineRenderer lineRenderer;
[Range(6,60)] //creates a slider - more than 60 is hard to notice
public int lineCount; //more lines = smoother ring
public float radius;
public float width;
void Start()
{
lineRenderer = GetComponent<LineRenderer>();
lineRenderer.loop = true;
Draw();
}
void Draw() //Only need to draw when something changes
{
lineRenderer.positionCount = lineCount;
lineRenderer.startWidth = width;
float theta = (2f * Mathf.PI) / lineCount; //find radians per segment
float angle = 0;
for (int i = 0; i < lineCount; i++)
{
float x = radius * Mathf.Cos(angle);
float y = radius * Mathf.Sin(angle);
lineRenderer.SetPosition(i, new Vector3(x, 0, y));
//switch 0 and y for 2D games
angle += theta;
}
}
}
请注意,这假定附加到您想要环的游戏对象。所以LineRenderer 中的Use World Space 选项应该被取消选中。还要记住,游戏对象的比例会影响点的位置和线的宽度。
把它放在地上(就像在一个单位选择圈里):
use world space
Alignment 设置为 Transform Z
SetPosition 中将要圈出的事物的位置添加到x 和y。可能同时将 0 替换为 0.1f 或 yOffset 变量以避免与地形发生 z-fighting。【讨论】:
圆可以使用着色器绘制 - 如果它在半径上从中心绘制像素。
【讨论】:
我有一个shader,我通常从它开始制作镜头光晕之类的效果,它会形成一个圆圈。使用着色器是最好的选择,因为你会得到完美的平滑和圆形。
此外,由于着色器更改不需要重新编译和重新进入播放模式,因此很容易试验和调整着色器。
【讨论】:
我建议为 GameObject 创建扩展方法。对我很好。
public static class GameObjectExtension
{
const int numberOfSegments = 360;
public static void DrawCircle(this GameObject go, float radius,
float lineWidth, Color startColor, Color endColor, bool lineRendererExists=true)
{
LineRenderer circle = lineRendererExists ? go.GetComponent<LineRenderer>() : go.AddComponent<LineRenderer>();
circle.useWorldSpace = false;
circle.startWidth = lineWidth;
circle.endWidth = lineWidth;
circle.endColor = endColor;
circle.startColor = startColor;
circle.positionCount = numberOfSegments + 1;
Vector3 [] points = new Vector3[numberOfSegments + 1];
for (int i = 0; i < numberOfSegments + 1; i++)
{
float rad = Mathf.Deg2Rad * i;
points[i] = new Vector3(Mathf.Sin(rad) * radius, 0, Mathf.Cos(rad) * radius);
}
circle.SetPositions(points);
}
}
还有一点需要注意:如果没有应用LineRenderer 组件,最后一个参数必须是false
【讨论】: