#StackBounty: #unity Adding functionality to make individual anchor points of bezier continuous or non-continuous

Bounty: 50

I am creating bezier curves with the following code. The curves can be extended to join several bezier curves by shift clicking in the scene view.
My code has functionality for making the whole curve continuous or non-continuous. I realised that I need to make individual points (specifically anchor points) have this functionality.

I believe the most ideal way to go about this is creating a new class for the points with this functionality (making points continuous or non-continuous) since this can be used to add other properties that might be specific to the points. How can do this?

Path

[System.Serializable]
public class Path {

[SerializeField, HideInInspector]
List<Vector2> points;

[SerializeField, HideInInspector]
public bool isContinuous;

public Path(Vector2 centre)
{
    points = new List<Vector2>
    {
        centre+Vector2.left,
        centre+(Vector2.left+Vector2.up)*.5f,
        centre + (Vector2.right+Vector2.down)*.5f,
        centre + Vector2.right
    };
}

public Vector2 this[int i]
{
    get
    {
        return points[i];
    }
}

public int NumPoints
{
    get
    {
        return points.Count;
    }
}

public int NumSegments
{
    get
    {
        return (points.Count - 4) / 3 + 1;
    }
}

public void AddSegment(Vector2 anchorPos)
{
    points.Add(points[points.Count - 1] * 2 - points[points.Count - 2]);
    points.Add((points[points.Count - 1] + anchorPos) * .5f);
    points.Add(anchorPos);
}

public Vector2[] GetPointsInSegment(int i)
{
    return new Vector2[] { points[i * 3], points[i * 3 + 1], points[i * 3 + 2], points[i * 3 + 3] };
}

public void MovePoint(int i, Vector2 pos)
{

    if (isContinuous)
    { 

        Vector2 deltaMove = pos - points[i];
        points[i] = pos;

        if (i % 3 == 0)
        {
            if (i + 1 < points.Count)
            {
                points[i + 1] += deltaMove;
            }
            if (i - 1 >= 0)
            {
                points[i - 1] += deltaMove;
            }
        }
        else
        {
            bool nextPointIsAnchor = (i + 1) % 3 == 0;
            int correspondingControlIndex = (nextPointIsAnchor) ? i + 2 : i - 2;
            int anchorIndex = (nextPointIsAnchor) ? i + 1 : i - 1;

            if (correspondingControlIndex >= 0 && correspondingControlIndex < points.Count)
            {
                float dst = (points[anchorIndex] - points[correspondingControlIndex]).magnitude;
                Vector2 dir = (points[anchorIndex] - pos).normalized;
            points[correspondingControlIndex] = points[anchorIndex] + dir * dst;
                }
            }
        }
    }

    else {
         points[i] = pos;
    }
}

PathCreator

public class PathCreator : MonoBehaviour {

[HideInInspector]
public Path path;


public void CreatePath()
{
    path = new Path(transform.position);
}
}

PathEditor

[CustomEditor(typeof(PathCreator))]
public class PathEditor : Editor {

PathCreator creator;
Path path;

public override void OnInspectorGUI()
{
    base.OnInspectorGUI();
    EditorGUI.BeginChangeCheck();

    bool continuousControlPoints = GUILayout.Toggle(path.isContinuous, "Set Continuous Control Points");
    if (continuousControlPoints != path.isContinuous)
    {
        Undo.RecordObject(creator, "Toggle set continuous controls");
        path.isContinuous = continuousControlPoints;
    }

    if (EditorGUI.EndChangeCheck())
    {
        SceneView.RepaintAll();
    }
}

void OnSceneGUI()
{
    Input();
    Draw();
}

void Input()
 {
    Event guiEvent = Event.current;
    Vector2 mousePos = HandleUtility.GUIPointToWorldRay(guiEvent.mousePosition).origin;

    if (guiEvent.type == EventType.MouseDown && guiEvent.button == 0 && guiEvent.shift)
    {
        Undo.RecordObject(creator, "Add segment");
        path.AddSegment(mousePos);
    }
}

void Draw()
{

    for (int i = 0; i < path.NumSegments; i++)
    {
        Vector2[] points = path.GetPointsInSegment(i);
        Handles.color = Color.black;
        Handles.DrawLine(points[1], points[0]);
        Handles.DrawLine(points[2], points[3]);
        Handles.DrawBezier(points[0], points[3], points[1], points[2], Color.green, null, 2);
    }

    Handles.color = Color.red;
    for (int i = 0; i < path.NumPoints; i++)
    {
        Vector2 newPos = Handles.FreeMoveHandle(path[i], Quaternion.identity, .1f, Vector2.zero, Handles.CylinderHandleCap);
        if (path[i] != newPos)
        {
            Undo.RecordObject(creator, "Move point");
            path.MovePoint(i, newPos);
        }
    }
}

void OnEnable()
{
    creator = (PathCreator)target;
    if (creator.path == null)
    {
        creator.CreatePath();
    }
    path = creator.path;
}
}


Get this bounty!!!

#StackBounty: #unity #movement Emulating the movement of a differential drive robot

Bounty: 100

I want to emulate the movements of an Khepera-like roboter (so a differntial drive robot) using Unity. It has two engines, the engine speed is set over the network by RPC magic which ends up calling the function move(). That function calculates the desired acceleration and saves it in a member variable.

FixedUpdate() then tries to accelerate up/down to the desired speed and by the desired rotation on each frame. To not mess with the general physic engine I am not setting those values directly but am using AddRelativeForce() and AddRelativeTorque(). However I have two problems:

  • on a change of the desired velocity (the setpoint basically) the movement becomes very jerky. That is expected because the code doesn’t try to ensure a smooth transation, as a linear interpolation would do. I’m not sure how I could do that while continuing to use AddRelative{Torque|Force}().
  • The bigger problem is that the movement is wrong. The basic kinds of movement seem to work[1]. However when trying to driving in a cirlce (i.e. a steady Move(vL = 100, vR = 75), the green line) the robot moves completely irrational and I’m not sure why that is the case.

My code is as follows, some parts ommited for clarity:

private Vector3 acceleration;
private float phi;
public const float R = 0.5f;
public const float L = 1f;

// FixedUpdate  is called once per frame, before the physics engine starts
void FixedUpdate()
{
    /* ... */

    /* move. During the tests accelerating maximally lead to the following
     * maximal acceleartion:
     * sqrt(11.2^2+0.7^2+0.7^2) = 11.24366488294630737835
     *
     * So let's say 15 is the maximal value that can be set via the controller.
     * Currently there's weird shit happening where after the robot rotated it moves
     * extremly fast, so cap the maximal applied acceleration.*/
    const float MAX_ACCELEARTION = 15;

    /* As AccelerateTo() multiplies by the framerate (to get a smooth movement independent
     * of it) small accelerations such as (0.00558295, -0.00144335, 0.00295163) will lead
     * to an de-acceleartion of (-0.3, 0.1, -0.1) so that the robot stands still. However
     * that often overshoots.
     * So if the robot should not accelerate and the current acceleration is very small,
     * don't use AccelerateTo() but just modify it directly (though this is a kinda ugly
     * hack, an PID controller would lead to more realistic behaviour)
     */
    if (acceleration.Equals(new Vector3()) && rb.velocity.sqrMagnitude < Constants.DBL_EPSILON) {
        rb.velocity = new Vector3();
    } else {
        AccelerateTo(rb, acceleration, MAX_ACCELEARTION);
    }
    acceleration = acceleration * (1 - Time.deltaTime);

    /* rotate according to angles */
    rb.AddRelativeTorque(new Vector3(0, (phi * 180 / Mathf.PI) * Time.deltaTime * 5, 0), ForceMode.VelocityChange); // Force, Impulse
    phi = phi * (1 - Time.deltaTime);
}

/**
 *  https://gamedev.stackexchange.com/a/113203
 */
private void AccelerateTo(Rigidbody body, Vector3 targetVelocity, float maxAccel)
{
    Vector3 deltaV = targetVelocity - body.velocity;
    Vector3 accel = deltaV / Time.deltaTime;

    if (accel.sqrMagnitude > maxAccel * maxAccel)
    {
        accel = accel.normalized * maxAccel;
    }

    print(body.velocity + " ==> " + deltaV + " ==> " + accel);
    body.AddRelativeForce(accel);
}

public void Move(float vR, float vL)
{
    /* ... */

    /**
     * R = wheel radius
     * L = distance between wheels
     * phi = rotation angle (which way the robot is facing)
     *     = R/L (v_r - v_l)
     * dx = R/2 (v_r + v_l) cos(phi)
     * dy = R/2 (v_r + v_l) sin(phi)
     * https://www.coursera.org/learn/mobile-robot/lecture/GnbnD/differential-drive-robots
     */

    phi = R / L * (vR - vL);
    float dX = R / 2 * (vR + vL) * Mathf.Cos(phi);
    float dY = R / 2 * (vR + vL) * Mathf.Sin(phi);

    /* ... */

    /* move forward */
    acceleration = new Vector3(dY, 0, dX);
    print(acceleration);

}

[1] Sorry for the german legend, translation follows: “Im Uhrzeigersinn” = clockwise, “Gegen …” = CCW, “Vorwaerts” = forward, “Ruckwaerts” = backwards


Get this bounty!!!

#StackBounty: #unity #dll #force-feedback How to get a good Force Feedback .dll Feedback for Steering Wheels? || How to access Force Fe…

Bounty: 100

I want to implement a steering wheel with Force Feedback to my game and I encountered this problem:
I couldnt do it with performance.
I have found a .dll for that online, but it had issues like:

  1. It was not performant
  2. It made my steering wheel react too delayed

Otherwise I was not able to access the steering wheel.
Is it even possible to make a performant steering wheel and force feedback game with good performance?
How else can I access force feedback ?


Get this bounty!!!

#StackBounty: #unity #nautilus #gtk Ubuntu 16.04 broken menus for some apps always displayed

Bounty: 50

Running 16.04 & Unity on a new Dell XPS13 laptop, freshly installed.
The menus for some apps (terminal, nautilus) are always shown below the app title bar.
Some other apps like Chrome or Text editor/gedit do show correctly at the top bar as it is supposed to considering the use of global menus.

This is weird as it does not happen for both userids configured on this machine. The other user desktop shows menu for all apps at the top bar using global menus correctly.

See pic. And nevermind the Macbuntu theme, I just installed it to test with it, but the same behavior was experienced before I did it.

Any help?

Screenshot


Get this bounty!!!

#StackBounty: #unity #shaders #graphics #fragment-shader #cg Depth Intersection Shader

Bounty: 50

I am trying to create a shader in Unity that shows where intersections occur between objects.

Most of the shader I have so far is based off of this youtube tutorial. However, I have made some slight modifications to it. The main one being that it is only using a camera’s depth texture instead of the depthnormal texture.

Shader "Intersection/Unlit"
{
    Properties
    {
        _Color("Color", Color) = (0,0,0,0)
        _GlowColor("Glow Color", Color) = (1, 1, 1, 1)
        _FadeLength("Fade Length", Range(0, 2)) = 0.15
    }
    SubShader
    {
        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite On

        Tags
        {
            "RenderType" = "Transparent"
            "Queue" = "Transparent"
        }

        Pass
        {
            CGPROGRAM
            #pragma target 3.0
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float2 screenuv : TEXCOORD1;
                float4 vertex : SV_POSITION;
                float depth : DEPTH;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

                o.screenuv = ((o.vertex.xy / o.vertex.w) + 1) / 2;
                o.screenuv.y = 1 - o.screenuv.y;
                o.depth = -UnityObjectToViewPos(v.vertex).z *_ProjectionParams.w;

                return o;
            }

            sampler2D _CameraDepthTexture;
            fixed4 _Color;
            fixed3 _GlowColor;
            float _FadeLength;

            fixed4 frag (v2f i) : SV_Target
            {
                float screenDepth = Linear01Depth(tex2D(_CameraDepthTexture, i.screenuv));
                float diff = screenDepth - i.depth;
                float intersect = 0;

                if(diff > 0)
                    intersect = 1 - smoothstep(0, _ProjectionParams.w * _FadeLength, diff);

                fixed4 glowColor = fixed4(lerp(_Color.rgb, _GlowColor, pow(intersect, 4)), 1);

                fixed4 col = _Color * _Color.a + glowColor;
                col.a = _Color.a;
                return col;
            }
            ENDCG
        }
    }
}

This shader produces a result that looks like this.

enter image description here

However, this is a problem as there are large areas of the object that remain the initial blue colour. What I was expecting was something that looked like this.

enter image description here

I think the issue is caused when calculating screen depth from i.screenuv

float screenDepth = Linear01Depth(tex2D(_CameraDepthTexture, i.screenuv));

I have tried removing the difference check, this initially appeared to work. Although, when I placed an object in front of the object with this shader, the shader behaved as if there was a collision when there was not. As you can see below.

enter image description here

I would appreciate any help in resolving the issue


Get this bounty!!!

#StackBounty: #unity #tiles #tilemap #tile Runtime Access to Unity 2d Tiles

Bounty: 50

I’m trying to use unity’s 2017 tilemap features. What I would like to do is push a tile’s sprite up (change its offset I think is the terminology?) so that the sprite moves up pixel by pixel and the top of the sprite loops back around to the bottom. Basically, I want to animate my “Water” sprite without having to build 20 different versions of the sprite to achieve the same effect. I was able to do this in Rotorz tiles by accessing its Atlas’ MainTexture Offset or something like that but this product is discontinued. This animation is similar to the water in classic RPG games like Ultima 4.

More than that, i would just love to have runtime access to the tiles to do other things: change out the entire sprite on a single tile, change the color, etc.

I have made a custom Tile class using this example:
https://docs.unity3d.com/Manual/Tilemap-ScriptableTiles-Example.html

But this only seems to effect tiles at the time of placement. Womp womp. 🙁

Is this possible and does anyone have a good example? Docs on this feature are scarce.


Get this bounty!!!