Локальные координаты внутри куба - PullRequest
2 голосов
/ 02 апреля 2019

Рука робота (коллайдер - подвижная зона)

Иллюстрация проблемы

Я делаю виртуальный клон руки робота, и мне нужно, чтобы он перемещался по координатам внутри куба (подвижная область). Рука робота в данный момент контролируется тремя значениями: x, y и z. Эти значения могут привести голову робота-манипулятора ко всем четырем углам куба. значения изменяются от 0 до 100. Мне нужно, чтобы вектор3 в мировом пространстве единиц был преобразован в эти значения внутри куба. Я делаю это таким образом, чтобы весь роботизированный сборный домик можно было перемещать и вращать, не нарушая эту функцию. Любые идеи о том, как мне этого добиться?

Ответы [ 2 ]

3 голосов
/ 02 апреля 2019

Если это простой куб, то все, что вам нужно знать, это его размер ребра и сделать что-то вроде

// Set this e.g. in the Inspector
// or somewhere get it e.g. in Start like
// edgesize = transform.lossyScale.x;
public float edgesize;

public Vector3 RobotToUnityPosition(Vector3 input)
{
    var output = input;

    // first shift the values in order to map the values (0 to 100) to
    // (-50 to +50) 
    output -= Vector3.one * 50.0f;

    // now eliminate the factor 100
    // so you get (-0.5 to +0.5)
    output /= 100.0f;

    // finally scale it accordingly to the cube's edgesize
    // so get it mapped to (-0.5 * edgesize to +0.5 * edgesize)
    output *= edgesize;

    return output;

    // could ofcourse also be done in one line like
    return ((input - Vector3.one * 50) / 100.0f) * edgesize;
}

public Vector3Int UnityToRobotPosition(Vector3 input)
{
    // basically do it the other way round
    var output = input;

    // Get percentages
    // (-0.5 to +0.5)
    output /= edgesize;

    // scale it up to factor 100
    // (-50 to +50)
    output *= 100.0f;

    // shift the values back
    // (0 to 100)
    output += Vector3.one * 50.0f;

    // Until here you also could have done it again in one line like
    //var output = (intput / edgesize) * 100.0f + Vector3.one * 50.0f;

    // Now you might want to clamp the values
    output.x = Mathf.Clamp(output.x, 0, 100);
    output.y = Mathf.Clamp(output.y, 0, 100);
    output.z = Mathf.Clamp(output.z, 0, 100);

    // Finally you might want to get it as Vector3Int ? 
    // if not you can skip that and change the return type to Vector3
    return Vector3Int.FloorToInt(output);
}

Демо (я добавил кое-что только для того, чтобы продемонстрировать, как это работает)

enter image description here


Вот полный код, который я использовал, если вы хотите использовать его в качестве начальной точки

public class PositionConverter : MonoBehaviour
{
    public float edgesize;

    public Vector3 inputVector;
    // I used a transform here in order to simply drag around
    // the object in Unity (or set it via script)
    public Transform WorldSpacePosition;
    public Vector3 backtoRobot;

    // whether to automatically update backtoRobot using the WorldSpacePosition.localPosition;
    public bool autoupdate;

    private void Awake()
    {
        // I simply used the lossyScale.x as edgeSize
        edgesize = transform.lossyScale.x;
    }

    private void Update()
    {
        if(!autoupdate)return;

        UpdateRobotPosition();
    }

    // Just fancy stuff for being able to call that method via
    // the context menu
    [ContextMenu("UpdateWorldPosition")]
    private void UpdateWorldPosition()
    {
        WorldSpacePosition.localPosition = RobotToUnityPosition(inputVector);
    }

    // Just fancy stuff for being able to call that method via
    // the context menu
    [ContextMenu("UpdateRobotPosition")]
    private void UpdateRobotPosition()
    {
        backtoRobot = UnityToRobotPosition(WorldSpacePosition.localPosition);
    }

    public Vector3 RobotToUnityPosition(Vector3 input)
    {
        var output = input;

        // first shift the values since 0 means e.g. -x edge etc
        output.x -= Vector3.one * 50.0f;

        // eliminate the factor 100
        output /= 100.0f;

        // scale it according to the cube's edgesize
        output *= edgesize;

        return output;
    }

    public Vector3Int UnityToRobotPosition(Vector3 input)
    {
        // basically do it the other way round
        var output = input;

        // Get percentages
        output /= edgesize;

        // scale it up to factor 100
        output *= 100;

        // shift the values back
        output += Vector3.one * 50.0f;

        // you might want to clamp the values
        output.x = Mathf.Clamp(output.x, 0, 100);
        output.y = Mathf.Clamp(output.y, 0, 100);
        output.z = Mathf.Clamp(output.z, 0, 100);

        // you might want to get it as Vector3Int ? 
        // if not you can skip that and change the return type to Vector3
        return Vector3Int.FloorToInt(output);
    }

    // Just for drawing the WireCube for the bounds
    private void OnDrawGizmos()
    {
        edgesize = transform.lossyScale.x;
        Gizmos.matrix = transform.localToWorldMatrix;

        Gizmos.DrawWireCube(Vector3.zero, Vector3.one * edgesize);
    }
}
  • Добавьте его к пустому GameObject и установите желаемую шкалу в Transform
  • Добавить ребенка, например объект Sphere и ссылка на него как WorldSpacePosition
2 голосов
/ 02 апреля 2019

Это достаточно просто.Вы можете использовать компонент Transform для выполнения вычислений в локальном пространстве любых объектов.

// constants (choose as they fit your scene)
Vector3 cubeSize = new Vector3(100, 100, 100);
Vector3 cubePivotLocal = new Vector3(0, 0, 0);

// The actual calculation
Vector3 worldPos = (your target world position);
Vector3 localPos = Vector3.Scale((transform.InverseTransformPoint(worldPos) - cubePivotLocal), cubeSize);

// localPos contains position of the target point in the local space of the script holder (your robot)

Все преобразования (переводы, вращения, масштабирование) держателя скрипта и его родителя (деда, ...) принимаются всчет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...