我知道这可能不是一件容易的事情,因为我还没有在网上找到这样的代码示例,但是如果我想在拖动过程中输入鼠标,在用户一放开鼠标,计算成某种网格的切片时,我们就可以使用鼠标输入,那么我需要注意的是什么,以及对此最好的算法和数据结构是什么?
发布于 2021-11-01 15:31:27
从理论上讲,这并不是那么复杂--给定一个点a在圆表面的某个地方,从圆心射出一条射线穿过这个长度点r。这条线的端点是你切圆的外部边缘。重复饼片的另一个边缘。
Vector2 calcEdgePoint(Vector2 mouseDownPosition,Vector2 circleCenter, float circleRadius)
{
Ray2D ray = new Ray2D(circleCenter, mouseDownPosition - circleCenter);
return ray.GetPoint(circleRadius);
}
如何在您的统一游戏中实践这一点取决于您需要多准确,以及您希望如何处理用户输入。
一种简单的方法--我可能会首先尝试--是“预切片”披萨(圆圈)网格,并简单地跟踪用户拖过的部分来确定要减去的部分。
下面是一个快速而肮脏的例子。
PieSlice
脚本:PizzaPieSlicer
控制器的鼠标进入,退出和(可选)停留信息:using UnityEngine;
public class PieSlice : MonoBehaviour
{
MeshRenderer mr;
void Start()
{
mr = GetComponent<MeshRenderer>();
}
private void OnMouseEnter()
{
Debug.Log("entered");
PizzaPieSlicer.instance.SliceEnter(mr);
}
private void OnMouseExit()
{
PizzaPieSlicer.instance.SliceExit(mr);
}
}
控制器脚本跟踪批萨是否使用状态机“活动”。当没有片处于活动状态时,它会继续并分割饼。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PizzaPieSlicer : MonoBehaviour
{
[SerializeField] Transform pieParent;
[SerializeField] Material[] materials;
public static PizzaPieSlicer instance;
public enum State
{
slicing,
idle,
sliced
}
public List<Transform> slices = new List<Transform>(); // public for debugging
public State state; // public for debugging;
public int hit = 0; // maybe useful to count? public for debugging " "
void Start()
{
instance = this;
state = State.idle;
}
public void SliceEnter(MeshRenderer mr)
{
mr.sharedMaterial = materials[1];
state = State.slicing;
if (!slices.Contains(mr.transform))
{
slices.Add(mr.transform);
}
hit++;
}
public void SliceExit(MeshRenderer mr)
{
mr.sharedMaterial = materials[2];
state = State.idle;
}
public void SliceStay()
{
state = State.slicing;
}
void SliceIt()
{
var sliceParent = new GameObject().GetComponent<Transform>();
foreach(Transform t in slices)
{
t.SetParent(sliceParent);
}
sliceParent.position = new Vector3(1, 1, 1); //Do something more intelligent here
}
void Update()
{
switch (state)
{
case State.idle:
if(hit > 0)
{
Debug.Log("Slice it!");
SliceIt();
state = State.sliced;
}
break;
case State.slicing:
// do something
break;
case State.sliced:
// reset maybe?
break;
default:
break;
}
}
}
演示:
注意:我本打算让PieSlice脚本在OnMouseOver事件期间通知PizzaPieSlicer,但事实证明这可能是不必要的;不过,我认为我的脚本的状态机可能依赖一种可能不可靠的竞争条件(退出事件总是在输入事件之前触发) --更好的方法可能是保持一个堆栈按下enter并在退出时拉动;如果一个帧经过,而堆栈为空,则触发这个片段。
团结中的另一种方法(如果这是UI元素)是使用Image.FillMethod.Radial360
并根据用户的鼠标输入指定一个fillAmount
。这种方法的一个可能的缺点是图像填充起源被限制在四个基本点上;在其他地方开始填充需要首先旋转图像,如果sprite不是普通填充的话,这可能是不可取的。
https://gamedev.stackexchange.com/questions/197632
复制相似问题