I'm working on implementing rod bending by blend tree.
Once, I've made a system to achieve that but then after I found out it doesn't work correctly in every angles and situations.
I fills directionX
(First parameter of blend tree) and directionY
(Second parameter of blend tree) by using this code:
Vector3 projectedLineXY = Vector3.ProjectOnPlane(_baitHandler.transform.position - _context.rodTip.position, _context.rod.transform.forward);
float angleSignXY = Mathf.Sign(Vector3.Dot(Vector3.Cross(_context.rod.transform.up, projectedLineXY), _context.rod.transform.forward));
float angleXY = Vector3.Angle(_context.rod.transform.up, projectedLineXY) * angleSignXY;
Vector3 projectedLineZY = Vector3.ProjectOnPlane(_baitHandler.transform.position - _context.rodTip.position, _context.rod.transform.right);
float angleSignZY = Mathf.Sign(Vector3.Dot(Vector3.Cross(_context.rod.transform.up, projectedLineZY), -_context.rod.transform.right));
float angleZY = Vector3.Angle(_context.rod.transform.up, projectedLineZY) * angleSignZY;
_baitHandler.transform.position
is bait position and _context.rodTip.position
is tip of rod position. _context.rod
is rod gameObject and other things related to that are its directions.
Please if you know how I can achieve the correct solution for that, explain what exactly I can fill these 2 parameters of blend tree.
I hope it is helpful for anyone who is looking for implementing rod bending by blend tree. Finally I got to this after so many iterations:
private const float ROD_BEND_CORRECTION_ERROR = 0.01f;
private readonly int DIRECTION_X_HASH = Animator.StringToHash("directionX");
private readonly int DIRECTION_Y_HASH = Animator.StringToHash("directionY");
public void UpdateRodBend(float deltaTime, float strength = 1f)
{
for (int i = 0; i < 10; i++)
{
Vector3 line = bait.position - rodTip.position;
Vector3 projectedY = Vector3.ProjectOnPlane(line, rodTip.forward);
float angleSignY = Mathf.Sign(Vector3.Dot(Vector3.Cross(rodTip.up, projectedY), rodTip.forward));
float angleY = Vector3.Angle(-rodTip.up, projectedY) * angleSignY;
if (Mathf.Abs(angleY / 90) > ROD_BEND_CORRECTION_ERROR)
{
animator.SetDirectionY((angleY / 90) * deltaTime * rodBendingSmoothSpeed, strength);
animator.ForceUpdateRodAnimator();
}
line = bait.position - rodTip.position;
Vector3 projectedX = Vector3.ProjectOnPlane(line, rodTip.right);
float angleSignX = Mathf.Sign(Vector3.Dot(Vector3.Cross(_context.rodTip.up, projectedX), -rodTip.right));
float angleX = Vector3.Angle(-rodTip.up, projectedX) * angleSignX;
if (Mathf.Abs(angleX / 90) > ROD_BEND_CORRECTION_ERROR)
{
animator.SetDirectionX((angleX / 90) * deltaTime * rodBendingSmoothSpeed, strength);
animator.ForceUpdateRodAnimator();
}
}
}
public void SetDirectionX(float value, float maxLength)
{
Vector2 clamped = Vector2.ClampMagnitude(new Vector2(animator.GetFloat(DIRECTION_X_HASH) + value, animator.GetFloat(DIRECTION_Y_HASH)), maxLength);
animator.SetFloat(DIRECTION_X_HASH, clamped.x);
}
public void SetDirectionY(float value, float maxLength)
{
Vector2 clamped = Vector2.ClampMagnitude(new Vector2(animator.GetFloat(DIRECTION_X_HASH), animator.GetFloat(DIRECTION_Y_HASH) + value), maxLength);
animator.SetFloat(DIRECTION_Y_HASH, clamped.y);
}