C# 使用统一的碰撞器将圆形精灵分割成彩色碎片
我有一个统一的旋转圆精灵C# 使用统一的碰撞器将圆形精灵分割成彩色碎片,c#,unity3d,C#,Unity3d,我有一个统一的旋转圆精灵 private void Update() { transform.Rotate(0, 0, 10 * Time.deltaTime); } 在我的Start方法中,我想把这个精灵分成几个部分。我输入了一个颜色数组作为参数 private void SetColors(Color[] colors) { // divide into color pieces } 例如,我在红色、蓝色、绿色、黄色中传递,圆圈应如下所示 可能的颜色数量是无限的 圆圈本
private void Update()
{
transform.Rotate(0, 0, 10 * Time.deltaTime);
}
在我的Start
方法中,我想把这个精灵分成几个部分。我输入了一个颜色数组作为参数
private void SetColors(Color[] colors)
{
// divide into color pieces
}
例如,我在红色、蓝色、绿色、黄色中传递,圆圈应如下所示
可能的颜色数量是无限的
圆圈本身有一个圆圈触发器。当检测触发碰撞时,我想检测碰撞的颜色
private void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject == ball)
{
// Color hitColor = the color that was hit
}
}
可以用一个简单的圆形精灵吗
更新:
如果我说当圆被什么东西击中时,它总是在圆的顶部,那么这个问题可能更容易解决
我可能会使用一段时间内的旋转速度来计算当前的点击颜色。可能有点晚,但我发现这个问题非常复杂: 此组件放置在
画布中的空游戏对象上。它负责创建和更新分段(并使用圆碰撞器控制光标对象)
演示
图像
预制件上的设置
由于默认的旋钮
纹理,看起来很糟糕。。您应该使用质量更好的圆形纹理。我唯一能想到的就是利用并获得碰撞点处像素的颜色。但是,您需要使用碰撞器而不是触发器来执行此操作。话虽如此,但没有深入探讨,我认为最普通的方法就是为圆圈的每一部分实例化一个游戏对象。你想要这个答案的哪一部分:制作一个普通的圆圈精灵,让它被代码分割并自动着色,或者根据圆圈的哪一部分被触摸来获取对应的颜色?我需要这两个部分。我想给圆上色,我想得到碰撞检测。但我会更新我的问题
public class CircleController : MonoBehaviour
{
public RectTransform rectTransform;
public List<Color> InitialColors = new List<Color>();
private List<Circlesegment> segments = new List<Circlesegment>();
public Circlesegment circleSeggmentPrefab;
public float firstSegmentAngleOffset = 0f;
// maximum vertices to use for the circle
// equally spread over all segments so not always uses all of them
public int totalMaxVertices = 50;
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
// if 0 start first segment at top
var startAngle = firstSegmentAngleOffset;
var anglePerSegment = 360f / InitialColors.Count;
var verticesPerSegment = totalMaxVertices / InitialColors.Count;
foreach (var initialColor in InitialColors)
{
var segment = Instantiate(circleSeggmentPrefab, transform);
segment.Initialize(this, initialColor, verticesPerSegment, rectTransform.rect.width / 2f, startAngle, anglePerSegment);
segments.Add(segment);
startAngle += anglePerSegment;
}
}
// Used this to simulate the collisions using the mouse
private CircleCollider2D cursor;
//used this to simulate the collision using mouse
private void Update()
{
if (!cursor)
{
cursor = new GameObject("cursor simulator", typeof(CircleCollider2D)).GetComponent<CircleCollider2D>();
cursor.radius = 10;
cursor.enabled = false;
}
cursor.transform.position = Input.mousePosition;
if (Input.GetMouseButtonDown(0))
{
cursor.enabled = true;
}
else if (Input.GetMouseButtonUp(0))
{
cursor.enabled = false;
}
}
public void RemoveSegment(Circlesegment segment)
{
segments.Remove(segment);
Destroy(segment.gameObject);
if (segments.Count == 0)
{
Debug.Log("GameOver!");
return;
}
var startAngle = firstSegmentAngleOffset;
var anglePerSegment = 360f / segments.Count;
var verticesPerSegment = totalMaxVertices / segments.Count;
foreach (var circleSegment in segments)
{
circleSegment.AnimateTowards(verticesPerSegment, startAngle, anglePerSegment);
startAngle += anglePerSegment;
}
}
}
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(EdgeCollider2D))]
[RequireComponent(typeof(Image))]
public class Circlesegment : MonoBehaviour
{
[SerializeField] Image image;
[SerializeField] EdgeCollider2D collider;
[SerializeField] Rigidbody2D rigidBody;
[SerializeField] RectTransform rectTransform;
[SerializeField] private int _segments;
[SerializeField] private float _startAngle;
[SerializeField] private float _segmentAngle;
private float _radius;
private CircleController circleController;
public Color Color;
private void OnCollisionEnter2D(Collision2D other)
{
circleController.RemoveSegment(this);
}
public void Initialize(CircleController controller, Color color, int segments, float radius, float startAngle, float segmentAngle)
{
Color = color;
circleController = controller;
_radius = radius;
if (!image) image = GetComponent<Image>();
if (!collider) collider = GetComponent<EdgeCollider2D>();
if (!rigidBody) rigidBody = GetComponent<Rigidbody2D>();
if (!rectTransform) rectTransform = GetComponent<RectTransform>();
image.color = color;
rectTransform.sizeDelta = new Vector2(radius * 2, radius * 2);
UpdateSegment(segments, startAngle, segmentAngle);
}
public void AnimateTowards(int segments, float startAngle, float segmentAngle, float duration = 1f)
{
StopAllCoroutines();
StartCoroutine(AnimateTowardsroutine(segments, startAngle, segmentAngle, duration));
}
private IEnumerator AnimateTowardsroutine(int segments, float startAngle, float segmentAngle, float duration)
{
var timePassed = 0f;
var currentStartAngle = _startAngle;
var currentSegmentAngle = _segmentAngle;
while (timePassed <= duration)
{
var lerpFactor = timePassed / duration;
UpdateSegment(segments, Mathf.LerpAngle(currentStartAngle, startAngle, lerpFactor), Mathf.LerpAngle(currentSegmentAngle, segmentAngle, lerpFactor));
timePassed += Mathf.Min(duration - timePassed, Time.deltaTime);
yield return null;
}
UpdateSegment(segments, startAngle, segmentAngle);
}
public void UpdateSegment(int segments, float startAngle, float segmentAngle)
{
_segments = segments;
_startAngle = startAngle;
_segmentAngle = segmentAngle;
var arcPoints = new List<Vector2>();
var angle = 0f;
var arcLength = segmentAngle;
if (!Mathf.Approximately(Mathf.Abs(segmentAngle), 360)) arcPoints.Add(Vector2.zero);
// calculate procedural circle vertices
for (var i = 0; i <= segments; i++)
{
var x = Mathf.Sin(Mathf.Deg2Rad * angle) * _radius;
var y = Mathf.Cos(Mathf.Deg2Rad * angle) * _radius;
arcPoints.Add(new Vector2(x, y));
angle += (arcLength / segments);
}
if (!Mathf.Approximately(Mathf.Abs(segmentAngle), 360)) arcPoints.Add(Vector2.zero);
image.fillAmount = arcLength / 360f;
rigidBody.rotation = startAngle;
collider.points = arcPoints.ToArray();
}
// For testing
[ContextMenu("UpdateSegment")]
private void UpdateSegment()
{
UpdateSegment(_segments, _startAngle, _segmentAngle);
}
//For testing
[ContextMenu("AnimateTowards")]
private void AnimateTowards()
{
AnimateTowards(_segments, _startAngle, _segmentAngle);
}
}