i have a 2d character and i want to make its head pop off.
Add force seems the most logical but i cannot get any force and it also must depend on the characters rotation. So if hes laying sideways the head must shoot off to the left (or right).
public GameObject RagdollBody;
HingeJoint2D joint;
bool cut = false;
Rigidbody2D rb;
void Start()
{
joint = GetComponent<HingeJoint2D>();
rb = GetComponent<Rigidbody2D>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.name == "Blade" && !cut)
{
joint.enabled = false;
cut = true;
rb.AddForce(-RagdollBody.transform.forward * 500);
}
}
I watched a video that used -transform so it will shoot in the oppersite direction which is what i want. As the head is always 0,0,0 rotation, i need to get it from the parent but it still doesnt add any force.
You are using transform.forward, which represents the Z axis, or "inwards" if you will, in a 2d game.
If you want to add force upwards (relative to its orientation), i suggest trying this instead
rb.AddForce(RagdollBody.transform.up * 500);
Could it be possible that you need to be using "AddRelativeForce" instead of "AddForce" on the last line there?
If this script is placed on the head you're launching you could try:
public GameObject RagdollBody;
HingeJoint2D joint;
bool cut = false;
Rigidbody2D rb;
void Start()
{
joint = GetComponent<HingeJoint2D>();
rb = GetComponent<Rigidbody2D>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.name == "Blade" && !cut)
{
joint.enabled = false;
cut = true;
rb.AddRelativeForce(Vector2.up * 500);
}
}
or you could get the 2d rigid body all in the one line (only to save lines):
public GameObject RagdollBody;
HingeJoint2D joint;
bool cut = false;
void Start()
{
joint = GetComponent<HingeJoint2D>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.name == "Blade" && !cut)
{
joint.enabled = false;
cut = true;
GetComponent<Rigidbody2D> ().AddRelativeForce(Vector2.up * 500);
}
}
Related
C# Character Controller
I'm new to using unity and I having difficulty with the force being applied to the sprite. The jump vector 2 variable is fine but I'm having issue with the horizontal movement. The code is not detecting if the key is held down,it will only add force to either side if you constantly tap the key, then it will move in a direction.
I'm not sure if I cant use the rigid body for horizontal movement or the vector is not written correctly. If you could please respond with the possible issues and or solution that would be helpful, thanks.
public float JumpForce;
public float HorizontalForce;
bool isGrounded = false;
Rigidbody2D RB;
void Start()
{
RB = GetComponent<Rigidbody2D>();
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
if(isGrounded == true)
{
RB.AddForce(Vector2.up * JumpForce);
isGrounded = false;
}
}
if (Input.GetKeyDown(KeyCode.A))
{
RB.AddForce(Vector2.left * HorizontalForce);
}
if (Input.GetKeyDown(KeyCode.D))
{
RB.AddForce(Vector2.right * HorizontalForce);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("ground")) ;
{
if(isGrounded == false)
{
isGrounded = true;
}
}
}
}
You need GetButton() instead of GetButtonDown().
GetButtonDown is only true for a single frame, in which the button was pressed. GetButton returns true as long as you hold the button
I am trying to write a script for an enemy to chase a player for about 2 seconds and then stopping. I want to have the player run into a boxcollider and when this happens the enemy will chase the player for 2 seconds. I've been trying for a while and had no luck. I'm hoping someone with more skill can help me write this code so it works properly using Unity 2d. Thanks
void Start()
{
var x = 0;
var y = 0;
player = GameObject.Find("Player").GetComponent<PlayerMovement>().playerBox;
}
public void OnCollisionEnter2D(Collision2D collision)
{
//If the player is touching the knights targetting box, then run the command to chase.
if (collision.collider.tag == "Player")
{
isChasing = true;
chase();
}
}
public void chase()
{
if (isChasing)
{
var x = playerTransform.position.x - enemyTransform.position.x;
var y = playerTransform.position.y - enemyTransform.position.y;
knightRB.velocity = new Vector2(x / 20, y / 20);
StartCoroutine(StopChasing());
}
}
IEnumerator StopChasing()
{
yield return new WaitForSeconds(2);
isChasing = false;
}
Below is my implementation:
Transfrom target;
bool isChasing;
float speed = 5;
RigidBody knightRB;
// -----------------------------------------------------------------------------
// Sets up the knight
void Start()
{
target = GameObject.Find("Player").transform;
knightRB = GetComponent<RigidBody>();
}
// -----------------------------------------------------------------------------
//Checks for a collision with the player
void OnCollisionEnter2D(Collision2D collision)
{
//If the player is touching the knights targetting box, then run the command to chase.
if (collision.collider.tag == "Player" && !isChasing)
{
StartCoRoutine(ChaseSequence());
}
}
// -----------------------------------------------------------------------------
// handles the chase
void FixedUpdate()
{
Chase();
}
void Chase()
{
if (!isChasing)
return;
var direction = (target.position - transform.position).normalized;
knightRB.MovePosition(transfrom.position + direction * Time.deltaTime * speed);
}
// -----------------------------------------------------------------------------
// Stops and starts the chase sequence
IEnumerator ChaseSequence()
{
isChasing = true;
yield return new WaitForSeconds(2);
isChasing = false;
}
There are some assumptions I have made. Mainly that the this script belongs on the knight. Also the collider is what interacts with the environment. Meaning physically. If you have a trigger that does the detection you should be using OnTriggerEnter instead of OnCollisionEnter
I have a simple jumping game. In this game there are rotating platforms, and a player object.
Whenever the player clicks the mouse button, it should jump and sticks to the next platform and rotates with it, until he clicks again. I want the game object to jump perpendicular to the rotating platforms.
If i use Vector3.up the game object will fall down instead. But I want the player to jump in the direction of a green arrow and stick to the next platform.
I'm posting here, because I've posted on the Unity Forms 2 weeks ago and still got no answer.
TLDR:
here is what i've worked on recently :
my player code :
Rigidbody2D Rig;
public float Force =500;
public bool gamejump = true;
public Transform platformParent;
bool playerforce = false;
bool setpos = false;
Vector2 pos = new Vector2(0, 0);
public Collider2D Ccollider;
public bool bottom =false;
void Start()
{
Rig = GetComponent<Rigidbody2D>();
Ccollider = GetComponent<CircleCollider2D>();
}
private void FixedUpdate()
{
if (gamejump == true)
{
transform.SetParent(null);
Rig.isKinematic = false;
setpos = false;
}
else
{
transform.SetParent(platformParent);
Rig.AddForce(new Vector2(0, 0));
Rig.isKinematic = true;
if (setpos == false)
{
setpos = true;
transform.position = pos;
}
}
}
void OnTriggerStay2D(Collider2D other)
{
if (other.tag == "Rotate")
{
//if (Input.GetKey(KeyCode.Space))
if (Input.GetMouseButton(0))
{
gamejump = true;
if (bottom == true)
{
Rig.AddForce(other.transform.up * Force);
}
else
{
Rig.AddForce(other.transform.up * -Force);
}
}
}
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Rotate")
{
ContactPoint2D contact = collision.contacts[0];
pos = contact.point;
if (collision.contacts.Length>0)
{
bottom = true;
}
else
{
bottom = false;
}
gamejump = false;
}
}
}
and my platform code :
public bool counterclockwise;
Transform player;
player2 playerCode;
public Collider2D collidPlatform;
private int speed=100;
// Start is called before the first frame update
void Start()
{
player = GameObject.Find("player").GetComponent<Transform>();
playerCode = FindObjectOfType<player2>();
if (counterclockwise)
speed = -speed;
}
void FixedUpdate()
{
// float currentZ = transform.eulerAngles.z;
/* if (Limit == true)
{
if (currentZ > 180)
{
currentZ = 180;
}
Vector3 newEuler = new Vector3(0, 0, currentZ);
transform.eulerAngles = newEuler;
}
//transform.Rotate(new Vector3(0, 0, speed * Time.deltaTime));
}
*/
}
private void OnCollisionEnter2D(Collision2D collision)
{
playerCode.platformParent = transform;
playerCode.Ccollider = collidPlatform;
}
}
and still got crazy results, suddenly the player rotates in the air or dose not sticks to a platform and falls or when it sticks to a platform ,it
Increases platform's speed (i know it's because of rigid body that attaches to platforms but if i remove it and try to control it manually it dose not work the way i want ,so if you could give me suggestion on how to rotate platforms manually and without rigid body so i be able to control the speed .
if you make the player a child object of the platform using transform.parent, then jump using transform.up on the players local axis, if you want the player to land on the same position where they jumped, the player can remain parented to the rotating platform, otherwise you need to remove the player as a child object to the platform after you jump. But since you are using rigidbody physics, I think you will get mixed results from gravity.
This is the code i have wrtten so far which makes the player controlled charcter be able to jump contanstantly i only want them to be able to jump when on the ground.
void Update()
{
this.transform.Translate(Input.GetAxis("Horizontal"), 0, 0);
xdirectionMovement = Input.GetAxis("Horizontal") * runspeed; //GetAxisRaw("Horizontal")
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)) //makes player jump
{
GetComponent<Rigidbody2D>().AddForce(jumpdistance, ForceMode2D.Impulse);
Ensure you only allow jumping when the character is grounded. One approach to check for that is to use a downwards raycast and see if the hit is below a certain threshold:
void Update()
{
print(IsGrounded());
}
bool IsGrounded()
{
const float distanceToGround = 1f;
return Physics.Raycast(
transform.position, -Vector3.up, distanceToGround) != null;
}
Another is to use a CharacterController component and check its bool:
CharacterController controller = null;
void Start()
{
controller = GetComponent<CharacterController>();
}
void Update()
{
print(controller.isGrounded);
}
Another is to listen for a collision event and set a bool:
bool collides = false;
void FixedUpdate()
{
print(collides);
collides = false;
}
void OnCollisionStay(Collision collision)
{
collides = true;
}
Note that sometimes, it's good usability practice to allow a bit of leeway so the user can jump even if they miss the ground by a few pixels, or miss the timing by a few milliseconds. Good luck!
Add a bool to check if player is grounded, add Vectors and Colliders to determine where player is, relative to the ground.
private BoxCollider2D box;
Vector3 maxValue= box.bounds.max;
Vector3 minValue=box.bounds.minValue;
Vector2 x = new Vector2(max.x, minValue.y -0.1f);
Vector2 y = new Vector2(minValue.x, minValue.y - 0.1f);
Collider2D ground = Physics.OverlapArea(x,y);
bool jump = false;
if (ground != null)
{
jump = true;
}
Finally you can add the bool to your Input, for example,
if (Input.GetKeyDown(KeyCode.Space) && jump == true)
{
//player jump
}
I have one issue in unity 2d with my object , when i shoot the arrow to the box collider to the other element , and when it hit and go into child i mean arrow become child of parent (BOX) the child start to rotate to the left and to the right .. I really want to disable left and right rotation of the child .. the box (parent) still need to rotate as same as it was before.. i have code like this and my arrow in rigidbody2d is on kinematic mode...
this is script of the arrow ..
{
public float flySpeed = 20f;
private Rigidbody2D arrowBody;
private bool shouldFly;
// Start is called before the first frame update
void Start()
{
shouldFly = true;
arrowBody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if (shouldFly == true)
{
//make our pin fly
arrowBody.MovePosition(arrowBody.position + Vector2.up * flySpeed * Time.deltaTime);
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.tag == "target")
{
shouldFly = false;
transform.SetParent(collision.gameObject.transform);
} else if(collision.tag == "arrow")
{
SceneManager.LoadScene("quickGameOverScene");
}
}
}
I am really confused what you are trying to do. I do not understand if you want to freeze rotation or movement so i will post answers for both. In order to prevent translations and rotations caused by parent object you can use LateUpdate like this:
Quaternion InitRot;
Vector3 InitPos;
void Start () {
InitRot = transform.rotation;
InitPos = transform.position;
}
void Update()
{
//figuring out when to save position when attached to BOX
if(gameObject.transform.parent == null)
{
InitRot = transform.rotation;
InitPos = transform.position;
}
}
void LateUpdate () {
//If attached to box do not translate do not rotate
if (gameObject.transform.parent != null)
{
transform.rotation = InitRot;
transform.position = InitPos;
}
}
You can have more information about this solution from here
EDIT
Since the answer above did not work out for OP. I figured out what the actual problem is. OP's code is perfectly fine for moving the arrow but the problem is most likely where he rotates the box.
If he rotates the box using transform.Rotate(Vector3.forward* 90), there will be a distortion caused by same amount of rotation in each Update since frame times are not same in each Update. Therefore, he needs to rotate the box using Time.deltaTime for consistent rotation like this: transform.Rotate(Vector3.forward* 90*Time.deltaTime); This rotate the box same amount in each time interval and eliminate distortion. These are the scripts i used for the task and it works for me.
Script for the arrow:
public float flySpeed = 20f;
private Rigidbody2D arrowBody;
private bool shouldFly;
private Vector2 initPos;
private Quaternion initRot;
// Start is called before the first frame update
void Start()
{
shouldFly = true;
arrowBody = GetComponent<Rigidbody2D>();
//arrowBody.isKinematic = true;
initPos = gameObject.transform.position;
initRot = gameObject.transform.rotation;
}
// Update is called once per frame
void Update()
{
if (shouldFly == true)
{
//make our pin fly
arrowBody.MovePosition(arrowBody.position + Vector2.up * flySpeed * Time.deltaTime);
}
if(gameObject.transform.parent == null)
{
initPos = gameObject.transform.position;
initRot = gameObject.transform.rotation;
}
}
void LateUpdate()
{
if (gameObject.transform.parent != null)
{
gameObject.transform.position = initPos;
gameObject.transform.rotation = initRot;
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
Debug.Log("Collision happened");
if (collision.tag == "target")
{
shouldFly = false;
transform.SetParent(collision.gameObject.transform);
}
else if (collision.tag == "arrow")
{
SceneManager.LoadScene("quickGameOverScene");
}
}
And The script for rotating the box:
public float rotationSpeed = 70f;
void Update()
{
transform.Rotate(Vector3.back, rotationSpeed * Time.deltaTime);
}