【UE4】 좋은 느낌에 뿌린 좌표치를 취득하는 시도 【C++】

14383 단어 C++위 4

소개



중심 지점에서 무작위로 뭔가를 팝업하고 싶을 때는 상당히 있지요?
하지만 좋은 느낌에 뿌리려고하면 조금 번거롭거나합니다.
제대로 하려고 하면 콜리전 판정 등으로 할 수 있습니다만, 거기까지 할 생각은 없다… 귀찮은…

그렇다고 대략 실장하면 이런 느낌이 된다고는 생각합니다만
이런 프로그램을 모두 바퀴를 재개발하고 있다고 생각했기 때문에 내가 쓴 경우의 코드를 정리해 둡니다
더 좋은 방법 없을까 ~라고 생각하고 있기 때문에 스테디셀러 알고리즘이 있다면 알려주세요.
(이런 자주 사용하는 시스템의 처리는 Engine 측에서 준비하고 있다고 돕지만, 이것은 너무 요구할까)

실행 환경



UE4.24.3
Microsoft Visual Studio Community 2017 버전 15.9.21

구현



확인 방법



중심 지점에서 일정 범위 이내(250 이내)에 10개의 의자를 발생시킵니다.

「좋은 느낌」이란


  • 편향이 적다
  • 좌표는 어느 정도 떨어져 있습니다

  • 무작위로 획득할 때 편향



    구현한 코드


    // Fill out your copyright notice in the Description page of Project Settings.
    
    
    #include "JGSUtility.h"
    #include "Math/UnrealMathUtility.h"
    
    FVector UJGSUtility::GetNonOverlapVector(float maxRange,int index, float degree, float repossessionRange,const TArray<FVector>& vectorArray)
    {
        auto getRandomVector = [maxRange](FVector biasVector)
        {
            float xMin = FMath::Clamp((-maxRange) + biasVector.X, -maxRange, maxRange);
            float xMax = FMath::Clamp(maxRange + biasVector.X, -maxRange, maxRange);
            float yMin = FMath::Clamp((-maxRange) + biasVector.Y, -maxRange, maxRange);
            float yMax = FMath::Clamp(maxRange + biasVector.Y, -maxRange, maxRange);
            float xRange = FMath::RandRange(xMin, xMax);
            float yRange = FMath::RandRange(yMin, yMax);
            return FVector(xRange, yRange, 0);
        };
        float theta = FMath::DegreesToRadians(index * degree);
        int r = maxRange / 2;//中心点から最大範囲の中間の長さ
        FVector biasVector = FVector(FMath::Cos(theta) * r,FMath::Sin(theta) * r,0);
        FVector retVector = getRandomVector(biasVector);
        const int safeTryCount = 10;
        int count = 0;
        bool isLoopEnd = false;
        //とり続けると設定値次第では無限LOOPしかねないのでセーフラインを設けておく
        while (!isLoopEnd && count < safeTryCount)
        {
            isLoopEnd = true;
            for (const auto& vec : vectorArray)
            {
                //再取得範囲内だったら再取得
                float xMax = vec.X + repossessionRange;
                float xMin = vec.X - repossessionRange;
                if (xMin <= retVector.X && retVector.X <= xMax)
                {
                    retVector = getRandomVector(biasVector);
                    isLoopEnd = false;
                    break;
                }
                float yMax = vec.Y + repossessionRange;
                float yMin = vec.Y - repossessionRange;
                if (yMin <= retVector.Y && retVector.Y <= yMax)
                {
                    retVector = getRandomVector(biasVector);
                    isLoopEnd = false;
                    break;
                }
            }
            count++;
        }
        return retVector;
    }
    
    void UJGSUtility::GetNonOverlapVectorArray(float maxRange, int degree, float repossessionRange,int requestCount ,TArray<FVector>& OutVecArray)
    {
        OutVecArray.Empty();
        for (int i = 0; i < requestCount; i++)
        {
            FVector vector = GetNonOverlapVector(maxRange,i,degree,repossessionRange,OutVecArray);
            OutVecArray.Add(vector);
        }
    }
    
    

    해설



    이번에 구현한 코드는 간단하고, 랜덤으로 좌표를 취득할 때에 바이어스를 더해 줘 기존의 확정이 끝난 좌표에 어느 정도 입고 있으면 재취득하고 있을 뿐입니다
    문제는 이 바이어스를 어떻게 요구하는가입니다.

    r : 좌표 취득의 최대 범위
    θ : 취득 횟수 × 임의의 각도
    α : 최대 범위 좌표
    α’: α에서 절반 거리에 있는 좌표



    실행할 때의 설정값과 Blueprint




    Max Range
    Degree
    Repossesion Range
    Request Count


    250
    36도
    35
    10회




    결과



    아무것도 생각하지 않고 무작위로 한 경우






    "좋은 느낌"과는 거리가 멀다.

    이번 알고리즘을 시도한 결과






    꽤 좋은 느낌으로 장미 할 수 있었던 것 같습니다.

    결론



    아무튼 실제로 이 코드로 반복해 보면 알겠습니다만, 이것으로도 비교적 의자와 입을 때가 있습니다
    그것은 아무튼 safeCount 이내에 취득할 수 없는 경우도 있으므로, 어느 정도는 허용인가라고…
    이런 코드, 여러가지 게임으로 모두 바퀴의 재개발 하고 있다고 생각해요…
    정평화해 주었으면 한다…

    좋은 웹페이지 즐겨찾기