I know this is a well-known question. But I don't know what to do.

(Open the image in a new tab for better clarity)
That script FastIKFabric.cs is working perfectly (moreover it's from asset store) and as you can see in the inspector it does not have any using UnityEditor;. The line 250 is the last one from that script and the } is closed properly. As I said, the script does not have any errors.
What can I do? Thanks in advance for any answer! :)
Here is the script:
#if UNITY_EDITOR
#endif
using UnityEngine;
namespace DitzelGames.FastIK
{
/// <summary>
/// Fabrik IK Solver
/// </summary>
public class FastIKFabric : MonoBehaviour
{
/// <summary>
/// Chain length of bones
/// </summary>
public int ChainLength = 2;
/// <summary>
/// Target the chain should bent to
/// </summary>
public Transform Target;
public Transform Pole;
/// <summary>
/// Solver iterations per update
/// </summary>
[Header("Solver Parameters")]
public int Iterations = 10;
/// <summary>
/// Distance when the solver stops
/// </summary>
public float Delta = 0.001f;
/// <summary>
/// Strength of going back to the start position.
/// </summary>
[Range(0, 1)]
public float SnapBackStrength = 1f;
protected float[] BonesLength; //Target to Origin
protected float CompleteLength;
protected Transform[] Bones;
protected Vector3[] Positions;
protected Vector3[] StartDirectionSucc;
protected Quaternion[] StartRotationBone;
protected Quaternion StartRotationTarget;
protected Transform Root;
// Start is called before the first frame update
void Awake()
{
Init();
}
void Init()
{
//initial array
Bones = new Transform[ChainLength + 1];
Positions = new Vector3[ChainLength + 1];
BonesLength = new float[ChainLength];
StartDirectionSucc = new Vector3[ChainLength + 1];
StartRotationBone = new Quaternion[ChainLength + 1];
//find root
Root = transform;
for (var i = 0; i <= ChainLength; i++)
{
if (Root == null)
throw new UnityException("The chain value is longer than the ancestor chain!");
Root = Root.parent;
}
//init target
if (Target == null)
{
Target = new GameObject(gameObject.name + " Target").transform;
SetPositionRootSpace(Target, GetPositionRootSpace(transform));
}
StartRotationTarget = GetRotationRootSpace(Target);
//init data
var current = transform;
CompleteLength = 0;
for (var i = Bones.Length - 1; i >= 0; i--)
{
Bones[i] = current;
StartRotationBone[i] = GetRotationRootSpace(current);
if (i == Bones.Length - 1)
{
//leaf
StartDirectionSucc[i] = GetPositionRootSpace(Target) - GetPositionRootSpace(current);
}
else
{
//mid bone
StartDirectionSucc[i] = GetPositionRootSpace(Bones[i + 1]) - GetPositionRootSpace(current);
BonesLength[i] = StartDirectionSucc[i].magnitude;
CompleteLength += BonesLength[i];
}
current = current.parent;
}
}
// Update is called once per frame
void LateUpdate()
{
ResolveIK();
}
private void ResolveIK()
{
if (Target == null)
return;
if (BonesLength.Length != ChainLength)
Init();
//Fabric
// root
// (bone0) (bonelen 0) (bone1) (bonelen 1) (bone2)...
// x--------------------x--------------------x---...
//get position
for (int i = 0; i < Bones.Length; i++)
Positions[i] = GetPositionRootSpace(Bones[i]);
var targetPosition = GetPositionRootSpace(Target);
var targetRotation = GetRotationRootSpace(Target);
//1st is possible to reach?
if ((targetPosition - GetPositionRootSpace(Bones[0])).sqrMagnitude >= CompleteLength * CompleteLength)
{
//just strech it
var direction = (targetPosition - Positions[0]).normalized;
//set everything after root
for (int i = 1; i < Positions.Length; i++)
Positions[i] = Positions[i - 1] + direction * BonesLength[i - 1];
}
else
{
for (int i = 0; i < Positions.Length - 1; i++)
Positions[i + 1] = Vector3.Lerp(Positions[i + 1], Positions[i] + StartDirectionSucc[i], SnapBackStrength);
for (int iteration = 0; iteration < Iterations; iteration++)
{
//https://www.youtube.com/watch?v=UNoX65PRehA
//back
for (int i = Positions.Length - 1; i > 0; i--)
{
if (i == Positions.Length - 1)
Positions[i] = targetPosition; //set it to target
else
Positions[i] = Positions[i + 1] + (Positions[i] - Positions[i + 1]).normalized * BonesLength[i]; //set in line on distance
}
//forward
for (int i = 1; i < Positions.Length; i++)
Positions[i] = Positions[i - 1] + (Positions[i] - Positions[i - 1]).normalized * BonesLength[i - 1];
//close enough?
if ((Positions[Positions.Length - 1] - targetPosition).sqrMagnitude < Delta * Delta)
break;
}
}
//move towards pole
if (Pole != null)
{
var polePosition = GetPositionRootSpace(Pole);
for (int i = 1; i < Positions.Length - 1; i++)
{
var plane = new Plane(Positions[i + 1] - Positions[i - 1], Positions[i - 1]);
var projectedPole = plane.ClosestPointOnPlane(polePosition);
var projectedBone = plane.ClosestPointOnPlane(Positions[i]);
var angle = Vector3.SignedAngle(projectedBone - Positions[i - 1], projectedPole - Positions[i - 1], plane.normal);
Positions[i] = Quaternion.AngleAxis(angle, plane.normal) * (Positions[i] - Positions[i - 1]) + Positions[i - 1];
}
}
//set position & rotation
for (int i = 0; i < Positions.Length; i++)
{
if (i == Positions.Length - 1)
SetRotationRootSpace(Bones[i], Quaternion.Inverse(targetRotation) * StartRotationTarget * Quaternion.Inverse(StartRotationBone[i]));
else
SetRotationRootSpace(Bones[i], Quaternion.FromToRotation(StartDirectionSucc[i], Positions[i + 1] - Positions[i]) * Quaternion.Inverse(StartRotationBone[i]));
SetPositionRootSpace(Bones[i], Positions[i]);
}
}
private Vector3 GetPositionRootSpace(Transform current)
{
if (Root == null)
return current.position;
else
return Quaternion.Inverse(Root.rotation) * (current.position - Root.position);
}
private void SetPositionRootSpace(Transform current, Vector3 position)
{
if (Root == null)
current.position = position;
else
current.position = Root.rotation * position + Root.position;
}
private Quaternion GetRotationRootSpace(Transform current)
{
//inverse(after) * before => rot: before -> after
if (Root == null)
return current.rotation;
else
return Quaternion.Inverse(current.rotation) * Root.rotation;
}
private void SetRotationRootSpace(Transform current, Quaternion rotation)
{
if (Root == null)
current.rotation = rotation;
else
current.rotation = Root.rotation * rotation;
}
void OnDrawGizmos()
{
#if UNITY_EDITOR
var current = this.transform;
for (int i = 0; i < ChainLength && current != null && current.parent != null; i++)
{
var scale = Vector3.Distance(current.position, current.parent.position) * 0.1f;
//Handles.matrix = Matrix4x4.TRS(current.position, Quaternion.FromToRotation(Vector3.up, current.parent.position - current.position), new Vector3(scale, Vector3.Distance(current.parent.position, current.position), scale));
//Handles.color = Color.green;
//Handles.DrawWireCube(Vector3.up * 0.5f, Vector3.one);
current = current.parent;
}
}
#endif
}
}