i am trying to make a grappling hook with the distance joint. but the distancejoints distance shrinks rapidly until the player collides with something. i want the distance to be set at whatever the distance is the moment that hook becomes a static rigidbody. Even more confusing is that my input getst reversed, (this does not happen if i use the i delete line heres my players script
using UnityEngine;
public class playerScript : MonoBehaviour
{
[Header("Components")]
[SerializeField] private Animator animator;
[SerializeField] private Rigidbody2D playerRb;
[Header("Movement")]
[SerializeField] private float moveSpeed = 5f;
[SerializeField] private float jumpForce = 5f;
[SerializeField] private float swingMoveSpeed = 8f;
[Header("Anchor")]
[SerializeField] private GameObject anchorPrefab;
private DistanceJoint2D distanceJoint;
private bool jointInitialized = false;
private anchorScript currentAnchor;
[SerializeField] private float minAngle = -60f;
[SerializeField] private float maxAngle = 60f;
[Header("Ground Check")]
[SerializeField] private LayerMask groundLayer;
[SerializeField] private Transform groundCheck;
[Header("Jump Buffer")]
[SerializeField] private float jumpBufferTime = 0.12f;
private float jumpBufferTimer;
private bool isSwinging = false;
private bool isGrounded;
private float horizontal;
private void Awake()
{
distanceJoint = GetComponent<DistanceJoint2D>();
}
void Update()
{
horizontal = Input.GetAxisRaw("Horizontal");
animator.SetBool("isWalking1", horizontal != 0);
if (Input.GetKeyDown(KeyCode.Space))
jumpBufferTimer = jumpBufferTime;
else
jumpBufferTimer -= Time.deltaTime;
if (Input.GetMouseButton(0))
{
ThrowAnchor();
}
else if ((Input.GetMouseButton(0)) == false && currentAnchor != null)
{
currentAnchor.Kill();
currentAnchor = null;
}
if (Input.GetKeyDown(KeyCode.F))
{
PlayerAttack();
}
if (isSwinging)
{
isGrounded = false;
animator.SetBool("isJumping", true);
animator.SetBool("isFalling", false);
}
}
void FixedUpdate()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, 0.2f, groundLayer);
animator.SetBool("isGrounded", isGrounded);
isSwinging = currentAnchor != null && currentAnchor.isAlive && currentAnchor.isAttached == true;
if (!isSwinging)
{
if (jointInitialized)
{
distanceJoint.enabled = false;
jointInitialized = false;
}
playerRb.linearVelocity = new Vector2(horizontal * moveSpeed, playerRb.linearVelocity.y);
}
else
{
if (!jointInitialized)
{
distanceJoint.connectedBody = currentAnchor.GetComponent<Rigidbody2D>();
distanceJoint.distance = Vector2.Distance(currentAnchor.offsetPlayerPos, currentAnchor.transform.position);
distanceJoint.enabled = true;
jointInitialized = true;
}
HandleSwingingInput();
}
if (horizontal != 0)
transform.localScale = new Vector3(Mathf.Sign(horizontal), 1, 1);
if (jumpBufferTimer > 0f && isGrounded)
{
playerRb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
jumpBufferTimer = 0f;
}
if (!isGrounded)
{
animator.SetBool("isJumping", playerRb.linearVelocity.y > 0);
animator.SetBool("isFalling", playerRb.linearVelocity.y < 0);
}
else
{
animator.SetBool("isJumping", false);
animator.SetBool("isFalling", false);
}
}
private void ThrowAnchor()
{
if (currentAnchor == null)
{
Vector3 direction = GetMouseDirection();
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(0f, 0f, angle);
float xOffset = transform.localScale.x == 1 ? 0.4f : -0.4f;
Vector3 spawnPos = transform.position + new Vector3(xOffset, -1.3f);
GameObject anchorObj = Instantiate(anchorPrefab, spawnPos, rotation);
currentAnchor = anchorObj.GetComponent<anchorScript>();
currentAnchor.Init(this);
}
}
public Vector3 GetMouseDirection()
{
Vector3 mouseScreen = Input.mousePosition;
mouseScreen.z = Camera.main.WorldToScreenPoint(transform.position).z;
Vector3 worldMouse = Camera.main.ScreenToWorldPoint(mouseScreen);
return worldMouse - transform.position;
}
private void PlayerAttack()
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.right, 1f);
if (hit.collider != null && hit.collider.CompareTag("Enemy"))
Debug.Log("Enemy hit!");
animator.SetTrigger("attack");
}
void HandleSwingingInput()
{
if (!isSwinging)
return;
Vector3 anchorpos = currentAnchor.transform.position;
Vector3 directionToAnchor = (anchorpos - currentAnchor.offsetPlayerPos).normalized;
Vector2 perpendicular = new Vector2(-directionToAnchor.y, directionToAnchor.x);
if (horizontal != 0 && currentAnchor.angle > minAngle && currentAnchor.angle < maxAngle)
{
playerRb.AddForce(perpendicular * (-1) * horizontal * swingMoveSpeed, ForceMode2D.Force);
}
}
}
and heres my anchors script
using UnityEditor;
using UnityEngine;
public class anchorScript : MonoBehaviour
{
[SerializeField] private float throwSpeed = 5f;
public bool isAlive { get; private set; } = true;
public bool isAttached { get; private set; } = false;
public float angle { get; private set; }
public Vector3 offsetPlayerPos;
public float yOffset = -1f;
private playerScript player;
private Rigidbody2D rb;
public void Init(playerScript playerScript)
{
player = playerScript;
}
void Start()
{
rb = GetComponent<Rigidbody2D>();
Vector2 direction = player.GetMouseDirection().normalized;
// 0 = horizontal, 1 = straight up
float upwardFactor = Mathf.Clamp01(direction.y);
// Reduce speed as aim goes up
float adjustedSpeed = throwSpeed * Mathf.Lerp(1f, 0.63f, upwardFactor);
rb.linearVelocity = direction * adjustedSpeed;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Kill();
}
if (isAttached)
{
Vector3 offsetPlayerPos = player.transform.position - new Vector3(0 , yOffset);
Vector2 playerToAnchor = (offsetPlayerPos - transform.position);
angle = Mathf.Atan2(playerToAnchor.y, playerToAnchor.x) * Mathf.Rad2Deg + 90f;
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (!isAlive)
return;
if (collision.gameObject.CompareTag("Player"))
return;
rb.linearVelocity = Vector2.zero;
rb.bodyType = RigidbodyType2D.Static;
isAttached = true;
//DeployRope();
}
public void Kill()
{
isAlive = false;
Destroy(gameObject);
}
//private void DeployRope()
//{
//}
}
i am pretty sure the line in fixed update “distanceJoint.distance = Vector2.Distance(currentAnchor.offsetPlayerPos, currentAnchor.transform.position);”
is called every frame and that causes the shrinking distance, i have no clue how to solve this and i have no clue why the input gets reversed. Its gotta be something with the Atan2 angle calculation done in anchorScript?