2016-09-01 4 views
0

내 오브젝트가 따라야 할 매끄럽고 무작위적인 경로를 그려야하며 2 차 베 지어 곡선을 사용하기로 마음 먹었습니다 (하지만 다른 아이디어는 가능합니다).2 차 베 지어 곡선으로 랜덤 경로 그리기

내 코드가 내 개체를 무작위로 움직이지만 부드러운 방식으로 움직이지 않습니다.

미리보기 : https://youtu.be/Eg9PEKuH4zA

내 질문은 : 어떻게 방향이 원활하게 변경 할 수 있습니까? 베 지어 솔루션을 완전히 버려야합니까? 아니면 원하는 코드를 구현할 수있는 방법이 있습니까? 당신은 몇 가지 중간 지점 A에서 B로가는 곡선이있는 경우

using UnityEngine; 
using System.Collections; 
using System.Collections.Generic; 

public class Lights : MonoBehaviour { 
    public float paintHeight = -90.0f; 
    public static int NUMBER_OF_LIGHTS = 3; 
    private static int BEZIER_PATH_POINTS = 100; 
    private float GOLDEN_COLOR_RATIO = 0.618033988749895f; 
    private Light[] lights = new Light[NUMBER_OF_LIGHTS]; 

    Vector3 RandomPoint() { 
     float obj_width = gameObject.GetComponent<RectTransform>().rect.width; 
     float screenX = Random.Range(-obj_width/2, obj_width/2); 

     float obj_height = gameObject.GetComponent<RectTransform>().rect.height; 
     float screenY = Random.Range(-obj_height/2, obj_height/2); 

     return new Vector3(screenX, screenY, -paintHeight); 
    } 


    Vector3 QuadraticBezierPoint(Vector3 startPoint, Vector3 endPoint, Vector3 vertexPoint, float t) { 
     /* 
     *   vertex 
     *  /╲ 
     *  / ╲ 
     * /p ╲ 
     * /. . ╲ 
     * /.  · ╲ 
     * /·   · ╲ 
     * start   · end 
     * 
     * 0 < t < 1 
     * 
     * B(t) = (1 - t)^2 * P0 + 2 * (1-t) * t * P1 + t^2 * P2 
     * 
     */ 
     return Mathf.Pow((1 - t), 2) * startPoint + 2 * (1 - t) * t * vertexPoint + Mathf.Pow(t, 2) * endPoint; 
    } 

    Color RandomColor() { 
     float h = Random.Range(0.0f, 1.0f) + GOLDEN_COLOR_RATIO; 
     h %= 1; 
     return Color.HSVToRGB(h, 0.99f, 0.99f); 
    } 

    void Start() { 
     for (int i = 0; i < NUMBER_OF_LIGHTS; i++) { 
      GameObject light_obj = new GameObject(); 
      Light light = light_obj.AddComponent<Light>(); 
      light.type = LightType.Point; 
      light.range = 10.0f; 
      light.intensity = 3.5f; 
      light.renderMode = LightRenderMode.ForcePixel; 
      light.name = "Light" + i; 
      light.transform.parent = gameObject.transform; 
      lights[i] = light; 
     } 

     StartCoroutine("Move"); 
    } 

    IEnumerator Move() { 
     Dictionary<string, Vector3>[] light_points = new Dictionary<string, Vector3>[NUMBER_OF_LIGHTS]; 
     Dictionary<string, Color>[] light_colors = new Dictionary<string, Color>[NUMBER_OF_LIGHTS]; 
     for (int i = 0; i < NUMBER_OF_LIGHTS; i++) { 
      light_points[i] = new Dictionary<string, Vector3>(); 
      light_colors[i] = new Dictionary<string, Color>(); 
      //light_points[i]["startPoint"] = RandomPoint(); 
      //light_points[i]["vertexPoint"] = RandomPoint(); 
      light_points[i]["endPoint"] = RandomPoint(); 
      light_colors[i]["nextColor"] = RandomColor(); 
     } 

     while(true) { 
      for (int i = 0; i < NUMBER_OF_LIGHTS; i++) { 
       light_points[i]["startPoint"] = light_points[i]["endPoint"]; 
       light_points[i]["vertexPoint"] = RandomPoint(); 
       light_points[i]["endPoint"] = RandomPoint(); 

       light_colors[i]["currentColor"] = light_colors[i]["nextColor"]; 
       light_colors[i]["nextColor"] = RandomColor(); 
      } 

      for (int i = 0; i < BEZIER_PATH_POINTS; i++) { 
       float percent = (float)i/BEZIER_PATH_POINTS; 
       for (int j = 0; j < NUMBER_OF_LIGHTS; j++) { 
        lights[j].transform.localPosition = QuadraticBezierPoint(
         light_points[j]["startPoint"], 
         light_points[j]["endPoint"], 
         light_points[j]["vertexPoint"], 
         percent 
        ); 
        lights[j].color = Color.Lerp(light_colors[j]["currentColor"], light_colors[j]["nextColor"], percent); 
       } 
       yield return new WaitForSeconds(0.02f); 
      } 
     } 
    } 
} 
+0

비디오가 실제로 도움이되지 않습니다. 흐릿한 빛이 흐릿한 배경에서 움직이므로 어떤 경로가 추적되는지 알 수 없습니다. 실제 문제를 설명함으로써 시작하십시오. 단일 곡선이 매끄 럽기 때문에 하나의 곡선에서 다음 곡선으로가는 것이 원활하지 않은 문제입니까? 그렇다면 솔루션은 3 차 곡선과 같이 고차 곡선이 더 좋은 G1 또는 G2 연속성을 보장합니다. 그리고 그 시점에서, Catmul-Rom 곡선을 사용하는 것은 더 명확합니다. 정의 된 점을 통과하기 때문에 (곡선의 각 섹션이 베 지어 형식으로 변환됩니다) –

답변

1

, 당신은 그에 따라 C를 선택해야합니다 :

* 부드러운 == 갑작스런 방향은

내 코드가 변경되지 않습니다 B에서의 각도 (A, B, C)가 너무 작거나 너무 크지 않도록한다.

또한 중간 지점을 적절한 방식으로 선택해야합니다 (예 : https://www.particleincell.com/2012/bezier-splines/이므로 방향 변경이 너무 크지 않습니다.

0

NURBS 또는 다른 스플라인을 사용할 수 있지만 게시 한 항목에 따라 매끄러운 커브를 얻는 더 쉬운 방법이있을 수 있습니다.

작성중인 각 곡선은 코드 시작, 정점 및 끝에서 3 포인트를가집니다. 그것들을 S, V, E라고 부르 자. 또한 시간을 통해 그들을 보아라. 그래서 {S0,V0,E0}는 첫번째 곡선을 만들고, {S1,V1,E1}는 두 번째 곡선을 만든다.

지금 바로 S1=E0, S2=E1 등을 확인하십시오. 즉, 라이트가 무작위로 점프하지 않지만 Bezier 커브를 전환 할 때 모션이 갑자기 바뀔 수 있습니다.

동작이 원활하게 수행되도록하려면 S1 = E0 = 0.5 * (V0+V1)을 확인하십시오. 실제로 S0와 V0를 무작위로 생성한다는 것입니다. 그런 다음 새로운 모든 곡선에 대해 새 V를 생성하고 이전 V와 새 V 사이의 중간 점을 곡선 중단 점으로 만듭니다.

균일 한 차수 2 B- 스플라인을 갖는 것과 같습니다.

다음은 예시 일 수있는 코드입니다.

// initialize with randomness 
// we need a previous v and a current v for the first iteration 
// So, the first start point will be halfway between these two points 
prev_v = random_point() 
v = random_point() 

while(true) 
{ 
    next_v = random_point() 
    s = 0.5 * (prev_v + v) // s is halfway between prev_v and v 
    e = 0.5 * (v + next_v) // e is halfway between v and next_v 
    yield_movement_bezier(s, v, e) 

    // prep for next iteration 
    prev_v = v 
    v = next_v 
} 
+0

나는 그것이 효과가 있다고 생각하지 않습니다. https://ibin.co/31dRdvQTxJDw.jpg – alexandernst

+0

다이어그램에서 E0는 V0과 V1의 중간 점에 있어야합니다. 이 방법을 사용하면 임의의 추가 E 값, 즉 V 값을 무작위로 생성하지 않습니다. 좀 더 명확하게하려고 의사 코드를 추가하겠습니다. – tfinniga