Assistance with unity 2d melee attack - c#

I'm making a 2D platform fighter but I've looked all over the internet and I'm not sure i can find what I'm looking for. I'm trying to make a melee attack to when you hit R-click on the mouse it dashes in the direction you are walking.
Ill try and figure out knock-back or dmg later. Any help with the movement of the script?
I'll list my current movement code below.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace NinjaController {
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(Collider2D))]
public class NinjaController : MonoBehaviour {
private Rigidbody2D RBody { get; set; }
[SerializeField]
private PhysicsParams physicsParams;
public Vector2 Velocity { get { return(RBody.velocity); } }
public Vector2 VelocityRelativeGround { get { return(Velocity / PhysicsParams.onGroundMaxVelHorizontal); } }
private float timeRealLastGroundCollision = 0;
private float timeRealLastWallLeftCollision = 0;
private float timeRealLastWallRightCollision = 0;
public bool IsOnGround {
get {
return GetIsColliding(timeRealLastGroundCollision);
}
}
public bool IsOnWallLeft {
get {
return GetIsColliding(timeRealLastWallLeftCollision);
}
}
public bool IsOnWallRight {
get {
return GetIsColliding(timeRealLastWallRightCollision);
}
}
public bool IsInAir { get { return isPlayerInAir; } }
private bool GetIsColliding(float timeLastCollision) {
return(Time.realtimeSinceStartup < timeLastCollision + 0.05f);
}
private Vector2 currentVelocity = Vector2.zero;
private Vector2 currentForce = Vector2.zero;
private float EntityMass { get { return(PhysicsParams.playerMass); } }
private bool isPlayerInAir = false;
private bool keyJumpRetrigger = false;
private bool keyJumpPressed = false;
private bool isPlayerOnWall = false;
public PhysicsParams PhysicsParams {
get { return physicsParams; }
set { physicsParams = value; }
}
public Vector2 CurrentForce { get { return currentForce; } }
public bool IsOnWall { get { return isPlayerOnWall; } }
private List<Renderer> allRenderers;
public List<Renderer> AllRenderers { get { return allRenderers; } }
public Vector3 Position {
get {
return transform.position;
}
set {
transform.position = value;
}
}
public Vector2 Position2D {
get {
return transform.position;
}
set {
transform.position = value;
}
}
public void Awake() {
RBody = GetComponent<Rigidbody2D>();
allRenderers = new List<Renderer>(GetComponentsInChildren<Renderer>(true));
}
public void Update() {
//let's reset forces to 0 and then add regular gravitation
SimResetForce();
SimAddForce(new Vector2(0, PhysicsParams.gameGravity) * EntityMass);
//process key input (like jumping key pressed, etc...)
ProcessInput();
//simulate position and velocity based on all acting forces
ComputeVelocity(Time.deltaTime);
//collision detection with static world
isPlayerOnWall = IsOnWallLeft || IsOnWallRight;
isPlayerInAir = IsOnGround == false;
}
private void SimResetForce() {
currentForce = Vector2.zero;
}
private void SimAddForce(Vector2 force) {
currentForce += force;
}
private void ComputeVelocity(float dt) {
currentVelocity += (currentForce / EntityMass) * dt;
//let's cap the speed in case its higher than the max
if (isPlayerInAir) {
currentVelocity.x = Mathf.Clamp(currentVelocity.x, -PhysicsParams.inAirMaxVelHorizontal, PhysicsParams.inAirMaxVelHorizontal);
} else {
currentVelocity.x = Mathf.Clamp(currentVelocity.x, -PhysicsParams.onGroundMaxVelHorizontal, PhysicsParams.onGroundMaxVelHorizontal);
}
RBody.velocity = currentVelocity;
}
private void ProcessInput() {
bool isKeyDownJump = Input.GetButton("Jump");
float inputAxisX = Input.GetAxisRaw("Horizontal");
bool isKeyDownLeft = inputAxisX < -0.5f;
bool isKeyDownRight = inputAxisX > 0.5f;
//-----------------
//JUMPING LOGIC:
//player is on ground
if (isPlayerInAir == false) {
//in case the player is on ground and does not press the jump key, he
//should be allowed to jump
if (isKeyDownJump == false) {
keyJumpRetrigger = true;
}
//did player press down the jump button?
if (isKeyDownJump == true && keyJumpRetrigger == true) {
keyJumpPressed = true;
keyJumpRetrigger = false;
//when pressing jump on ground we set the upwards velocity directly
currentVelocity = new Vector2(currentVelocity.x, PhysicsParams.jumpUpVel);
}
} else if (isPlayerOnWall == true) {
//let's allow jumping again in case of being on the wall
if (isKeyDownJump == false) {
keyJumpRetrigger = true;
}
if (currentVelocity.y < 0) {//apply friction when moving downwards
SimAddForce(new Vector2(0, PhysicsParams.wallFriction) * EntityMass);
}
if (currentVelocity.y < PhysicsParams.wallFrictionStrongVelThreshold) {//apply even more friction when moving downwards fast
SimAddForce(new Vector2(0, PhysicsParams.wallFrictionStrong) * EntityMass);
}
if (isKeyDownJump == true && keyJumpRetrigger == true) {
keyJumpPressed = true;
keyJumpRetrigger = false;
//in case we are moving down -> let's set the velocity directly
//in case we are moving up -> sum up velocity
if (IsOnWallLeft == true) {
if (currentVelocity.y <= 0) {
currentVelocity = new Vector2(PhysicsParams.jumpWallVelHorizontal, PhysicsParams.jumpWallVelVertical);
} else {
currentVelocity = new Vector2(PhysicsParams.jumpWallVelHorizontal, currentVelocity.y + PhysicsParams.jumpWallVelVertical);
}
} else if (IsOnWallRight == true) {
if (currentVelocity.y <= 0)
currentVelocity = new Vector2(-PhysicsParams.jumpWallVelHorizontal, PhysicsParams.jumpWallVelVertical);
else
currentVelocity = new Vector2(-PhysicsParams.jumpWallVelHorizontal, currentVelocity.y + PhysicsParams.jumpWallVelVertical);
}
}
}
//did player lift the jump button?
if (isKeyDownJump == false) {
keyJumpPressed = false;
}
//let's apply force in case we are holding the jump key during a jump.
if (keyJumpPressed == true) {
SimAddForce(new Vector2(0, PhysicsParams.jumpUpForce) * EntityMass);
}
//however let's stop doing that as soon as we fall down after the up-phase.
if (keyJumpPressed == true && currentVelocity.y <= 0) {
keyJumpPressed = false;
}
//let's apply additional gravity in case we're in air moving up but not holding the jump button
if (keyJumpPressed == false && isPlayerInAir == true && currentVelocity.y > 0) {
SimAddForce(new Vector2(0, PhysicsParams.jumpGravity) * EntityMass);
}
//-----------------
//IN AIR SIDEWAYS:
if (isPlayerInAir == true) {
//steering into moving direction (slow accel)
if (isKeyDownLeft == true && currentVelocity.x <= 0)
SimAddForce(new Vector2(-PhysicsParams.inAirMoveHorizontalForce, 0) * EntityMass);
else if (isKeyDownRight == true && currentVelocity.x >= 0)
SimAddForce(new Vector2(PhysicsParams.inAirMoveHorizontalForce, 0) * EntityMass);
//steering against moving direction (fast reverse accel)
else if (isKeyDownLeft == true && currentVelocity.x >= 0)
SimAddForce(new Vector2(-PhysicsParams.inAirMoveHorizontalForceReverse, 0) * EntityMass);
else if (isKeyDownRight == true && currentVelocity.x <= 0)
SimAddForce(new Vector2(PhysicsParams.inAirMoveHorizontalForceReverse, 0) * EntityMass);
}
//-----------------
//ON GROUND SIDEWAYS:
if (isPlayerInAir == false) {
//steering into moving direction (slow accel)
if (isKeyDownLeft == true && currentVelocity.x <= 0)
SimAddForce(new Vector2(-PhysicsParams.onGroundMoveHorizontalForce, 0) * EntityMass);
else if (isKeyDownRight == true && currentVelocity.x >= 0)
SimAddForce(new Vector2(PhysicsParams.onGroundMoveHorizontalForce, 0) * EntityMass);
//steering against moving direction (fast reverse accel)
else if (isKeyDownLeft == true && currentVelocity.x >= 0)
SimAddForce(new Vector2(-PhysicsParams.onGroundMoveHorizontalForceReverse, 0) * EntityMass);
else if (isKeyDownRight == true && currentVelocity.x <= 0)
SimAddForce(new Vector2(PhysicsParams.onGroundMoveHorizontalForceReverse, 0) * EntityMass);
//not steering -> brake due to friction.
else if (isKeyDownLeft != true && isKeyDownRight != true && currentVelocity.x > 0)
SimAddForce(new Vector2(-PhysicsParams.groundFriction, 0) * EntityMass);
else if (isKeyDownLeft != true && isKeyDownRight != true && currentVelocity.x < 0)
SimAddForce(new Vector2(PhysicsParams.groundFriction, 0) * EntityMass);
//in case the velocity is close to 0 and no keys are pressed we should make the the player stop.
//to do this let's first undo the prior friction force, and then set the velocity to 0.
if (isKeyDownLeft != true && isKeyDownRight != true && currentVelocity.x > 0 && currentVelocity.x < PhysicsParams.groundFrictionEpsilon) {
SimAddForce(new Vector2(PhysicsParams.groundFriction, 0) * EntityMass);
currentVelocity.x = 0;
} else if (isKeyDownLeft != true && isKeyDownRight != true && currentVelocity.x < 0 && currentVelocity.x > -PhysicsParams.groundFrictionEpsilon) {
SimAddForce(new Vector2(-PhysicsParams.groundFriction, 0) * EntityMass);
currentVelocity.x = 0;
}
}
}
public void ResetVelocity() {
currentVelocity = Vector2.zero;
}
public void OnCollisionStay2D(Collision2D collision) {
foreach (ContactPoint2D contactPoint in collision.contacts) {
if (GetIsVectorClose(new Vector2(0, 1), contactPoint.normal)) {
timeRealLastGroundCollision = Time.realtimeSinceStartup;
currentVelocity.y = Mathf.Clamp(currentVelocity.y, 0, Mathf.Abs(currentVelocity.y));
}
if (GetIsVectorClose(new Vector2(1, 0), contactPoint.normal)) {
timeRealLastWallLeftCollision = Time.realtimeSinceStartup;
currentVelocity.x = Mathf.Clamp(currentVelocity.x, 0, Mathf.Abs(currentVelocity.x));
}
if (GetIsVectorClose(new Vector2(-1, 0), contactPoint.normal)) {
timeRealLastWallRightCollision = Time.realtimeSinceStartup;
currentVelocity.x = Mathf.Clamp(currentVelocity.x, -Mathf.Abs(currentVelocity.x), 0);
}
if(GetIsVectorClose(Vector2.down, contactPoint.normal)) {
currentVelocity.y = Mathf.Clamp(currentVelocity.y, -Mathf.Abs(currentVelocity.y), 0);
}
}
}
private bool GetIsVectorClose(Vector2 vectorA, Vector2 vectorB) {
return(Mathf.Approximately(0, Vector2.Distance(vectorA, vectorB)));
}
public void OnLifeChanged (int life, Vector2 contactVector) {
const float forceEnemyCollision = 15.0f;
currentVelocity = contactVector.normalized * forceEnemyCollision;
}
public void ResetPlayer() {
currentVelocity = Vector2.zero;
}
}
}

For dashing, it will be something along the line of:
bool isDashing;
float currentDashTime = 0; // How long in seconds since the dash started.
float dashTime = 1f; // How long in seconds will the dash be.
float dashSpeed = 10f;
private void Update()
{
if (Input.GetMouseButtonDown(1)) // Right click
{
if (!isDashing) StartCoroutine(Dash());
}
}
private IEnumerator Dash()
{
isDashing = true;
currentDashTime = 0;
Vector2 facingDirection = new Vector2(transform.right.x, transform.right.y)
rb2d.AddForce(facingDirection * dashSpeed);
while (currentDashTime < dashTime)
{
currentDashTime += Time.deltaTime;
yield return null;
}
// If you want the character to stop after dashing ends.
// rb.velocity = Vector2.zero;
isDashing = false;
}
As for melee attacks, I'll recommend looking into 2D Raycasts, provided your enemies have colliders on them. You can raycast before you start dashing so you know what you will collide with during the dash beforehand.
RaycastHit2D hit = Physics2D.Raycast(transform.position, facingDirection);
if (hit.collider != null)
{
// Check for enemy, damage the enemy... etc.
}
Use Physics2D.RaycastAll if you want to get all enemies hit along a line. Physics2D.RayCast only returns the first collider hit.

Related

Need help translating unity's old input manager to the new input system

I'm new to using Unity and C# and I've been working on creating a movement system for a 2D platformer, and I've decided I want to switch to the new Unity Input System (because I can't find good information on the old one as all the search results I get are for the new one). I have it downloaded and installed and have watched a ton of videos but can't get any inputs to actually work in my game.
Here is the code which I need help translating:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class CharacterLogic : MonoBehaviour
{
private bool playerIsAlive = true;
Vector2 movementInput;
bool jumpInput;
bool doubleJumpInput;
private float sprintTimer;
private bool isSprinting;
private int jumpsRemaining = 1;
private bool facingRight = true;
private bool isGrounded;
private bool wallJumping = false;
[Header("Collision")]
public BoxCollider2D playerCollider;
public LayerMask jumpableGround;
[Header("Movement")]
public Rigidbody2D characterBody;
public float runSpeed = 7;
public float maxSpeed = 10;
public float jumpStrength = 11;
[Header("Camera Tracking")]
public CameraScript mainCamera;
public float zoomSpeed;
public float ZoomAmount;
public float maxZoomAmount;
[Header("Wall Jump System")]
public Transform frontCheck;
public float wallSlidingSpeed;
public float checkRadius;
public float xWallForce;
public float yWallForce;
public float wallJumpTime;
bool isTouchingFront;
bool wallSliding;
[Header("Animation Settings")]
public Animator animator;
private string currentState;
//Animation States
const string PLAYER_IDLE = "Idle";
const string PLAYER_RUN = "Running";
const string PLAYER_SPRINT = "Sprinting";
const string PLAYER_JUMP = "Jumping";
const string PLAYER_WALLSLIDE = "Wallslide";
[Header("Inputs")]
public PlayerInput playerInput;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
movementInput.x = Input.GetAxisRaw("Horizontal");
movementInput.y = Input.GetAxisRaw("Vertical");
isGrounded = Physics2D.BoxCast(playerCollider.bounds.center, playerCollider.bounds.size, 0f, Vector2.down, .1f, jumpableGround);
if (Input.GetButtonDown("Jump"))
{
if (!isGrounded)
{
if (wallSliding)
{
jumpsRemaining += -1;
}else if (jumpsRemaining > 0)
{
jumpInput = true;
doubleJumpInput = true;
}
}
else if (isGrounded)
{
jumpInput = true;
}
// Wall jump
if (!facingRight)
{
if (movementInput.x > 0 && wallSliding == true)
{
wallJumping = true;
}
}else if (facingRight)
{
if (movementInput.x < 0 && wallSliding == true)
{
wallJumping = true;
}
}
}
}
void FixedUpdate()
{
// Flip the character sprite's direction
if (facingRight == false && movementInput.x > 0 && !wallSliding && (isGrounded || doubleJumpInput))
{
Flip();
} else if (facingRight == true && movementInput.x < 0 && !wallSliding && (isGrounded || doubleJumpInput))
{
Flip();
}
// Jump
if (jumpInput && playerIsAlive && wallSliding != true)
{
Jump();
}
// Run
if (movementInput.x != 0 && playerIsAlive && wallSliding == false)
{
Run();
if (characterBody.velocity.x == maxSpeed)
{
mainCamera.xOffset = 6;
//mainCamera.ZoomOut(maxZoomAmount, zoomSpeed);
}else if (characterBody.velocity.x == -maxSpeed)
{
mainCamera.xOffset = -6;
}
else
{
if (movementInput.x > 0)
{
mainCamera.xOffset = 4;
}else if (movementInput.x < 0)
{
mainCamera.xOffset = -4;
}
}
}
// Idle
if (((movementInput.x == 0) && (movementInput.y == 0)) && playerIsAlive && wallSliding == false)
{
Idle();
ChangeAnimationState(PLAYER_IDLE);
}
// Reset sprint timer
if (movementInput.x == 0)
{
sprintTimer = 0;
mainCamera.xOffset = 0;
}
// Reset double jump
if (isGrounded)
{
jumpsRemaining = 1;
}
// Detect wall collisions
isTouchingFront = Physics2D.OverlapCircle(frontCheck.position, checkRadius, jumpableGround);
if (isTouchingFront == true && !isGrounded && Input.GetButton("Fire1"))
{
wallSliding = true;
}
else
{
wallSliding = false;
}
if (wallSliding && !wallJumping)
{
WallSlide();
ChangeAnimationState(PLAYER_WALLSLIDE);
}
if (wallJumping == true)
{
ChangeAnimationState(PLAYER_JUMP);
Invoke("SetWallJumpingToFalse", wallJumpTime);
characterBody.velocity = new Vector2(xWallForce * movementInput.x, yWallForce);
Flip();
}
//Debug.Log(jumpsRemaining);
}
/// <summary>
/// This function sets the character's velocity in the Y axis to the value of `jumpStrength`,.
/// It also preserves the character's current velocity along the Y axis.
/// </summary>
public void Jump()
{
//Debug.Log("Normal Jump");
jumpsRemaining += -1;
Vector2 velocity = characterBody.velocity;
if ((velocity.x > 0 && movementInput.x > 0) || (velocity.x < 0 && movementInput.x < 0))
{
}
else
{
if (movementInput.x > 0)
{
velocity.x = 7;
}
else if (movementInput.x < 0)
{
velocity.x = -7;
}
}
velocity.y = jumpStrength;
characterBody.velocity = velocity;
jumpInput = false;
if (doubleJumpInput == true)
{
doubleJumpInput = false;
}
if (!isGrounded)
{
ChangeAnimationState(PLAYER_JUMP);
}
}
/// <summary>
/// This function sets the character's velocity in the X axis to the value of `runSpeed`.
/// It also preserves the character's current velocity along the Y axis.
/// </summary>
public void Run()
{
sprintTimer += Time.deltaTime;
Vector2 velocity = characterBody.velocity;
if (sprintTimer > 2 && characterBody.velocity.x != 0)
{
if (isGrounded)
{
if (movementInput.x > 0)
{
velocity.x = maxSpeed;
isSprinting = true;
ChangeAnimationState(PLAYER_SPRINT);
}
else if (movementInput.x < 0)
{
velocity.x = -maxSpeed;
isSprinting = true;
ChangeAnimationState(PLAYER_SPRINT);
}
} else
{
if (isSprinting == false)
{
if (velocity.x > 0)
{
velocity.x = runSpeed;
isSprinting = false;
ChangeAnimationState(PLAYER_RUN);
}
else if (velocity.x < 0)
{
velocity.x = -runSpeed;
isSprinting = false;
ChangeAnimationState(PLAYER_RUN);
}
}
}
}
else
{
if (movementInput.x > 0 && isGrounded)
{
velocity.x = runSpeed;
isSprinting = false;
ChangeAnimationState(PLAYER_RUN);
}
else if (movementInput.x < 0 && isGrounded)
{
velocity.x = -runSpeed;
isSprinting = false;
ChangeAnimationState(PLAYER_RUN);
}
}
characterBody.velocity = velocity;
}
public void Idle()
{
characterBody.velocity = new Vector2(0, characterBody.velocity.y);
}
private void Flip()
{
facingRight = !facingRight;
Vector3 scaler = transform.localScale;
scaler.x *= -1;
transform.localScale = scaler;
}
private void WallSlide()
{
//Flip();
characterBody.velocity = new Vector2(characterBody.velocity.x, Mathf.Clamp(characterBody.velocity.y, -wallSlidingSpeed, float.MaxValue));
}
private void ChangeAnimationState(string newState)
{
// Stop the same animation from interrupting itself
if (currentState == newState) return;
//Play the animation
animator.Play(newState);
// Reassign the current state to the new state
currentState = newState;
}
private void SetWallJumpingToFalse()
{
wallJumping = false;
jumpsRemaining = 1;
}
public void OnJump(InputAction.CallbackContext value)
{
Debug.Log("Jump");
}
public void OnMovement(InputAction.CallbackContext value)
{
Vector2 inputMovement = value.ReadValue<Vector2>();
Debug.Log("Jump");
}
}
If anyone can help dumb this down for me I'd be eternally grateful. As you can see from the last two functions, I am trying to trigger unity events, assign the events to functions and write to the Debug.log so that I can see it's working. For instance currently, it should say "Jump" when I press the button I've mapped to "Jump" in the action map, but in reality it just triggers the old input manager stuff normally and the new stuff does nothing.
I have the PlayerInput class correctly attached to the CharacterLogic script in the inspector, and I believe everything is set up correctly with the events calling the right action map and function from my code (screenshot attached)
Help?
I have tried following every guide I could see on youtube and they were overly complicated and I couldn't see how I could translate how my old input system was working over to their methods.
Yeah I figured out the actual issue. When you create a control scheme, you are given the "option" to add a requirement. It's not optional, if you don't add a requirement, it won't work. That should really be made a mandatory field.

I develop runner type game, and i have following issue: after slide character can jump twice

I make games in unity c#. I used isGrounded and Physics.SphereCast to detect collision between character and ground, but it didn't help. He still jumped twice. I added bool jumpDone that becomes false when a character jumps, so I thought double jump wouldn't happen, but it doesn't work.
public ParticleSystem coinSound;
public GameObject DeathButton;
public GameObject PauseButton;
public static int coins = 0;
public static bool slideDone = true;
public static Vector3 manBeforeSlide;
public float distance;
public static bool died = false;
public static bool OneTimeDeath = true;
public static bool play = false;
public static bool helloEnded = false;
public static bool EnviromentMoves = false;
public static bool tap, swipeLeft, swipeRight, swipeUp, swipeDown;
public static AudioSource collisionSound;
public static Animator animator;
private CharacterController cc;
private int mid = 0;
private int k = 0;
private float time = 0.4f;
private float dir;
private float currentDistance = 0f;
private float currentDir = 0f;
private bool isInMovement = false;
private bool jumpDone = true;
private bool isDraging = false;
private Vector2 startTouch, swipeDelta;
void Start()
{
collisionSound = GetComponent<AudioSource>();
animator = GetComponent<Animator>();
cc = GetComponent<CharacterController>();
}
void Update()
{
if (!helloEnded)
{
if (!animator.GetCurrentAnimatorStateInfo(0).IsName("Start"))
helloEnded = true;
}
if (play && !died)
{
tap = swipeDown = swipeUp = swipeLeft = swipeRight = false;
if (Input.GetMouseButtonDown(0))
{
tap = true;
isDraging = true;
startTouch = Input.mousePosition;
}
else if (Input.GetMouseButtonUp(0))
{
isDraging = false;
Reset();
}
if (Input.touches.Length > 0)
{
if (Input.touches[0].phase == TouchPhase.Began)
{
tap = true;
isDraging = true;
startTouch = Input.touches[0].position;
}
else if (Input.touches[0].phase == TouchPhase.Ended || Input.touches[0].phase == TouchPhase.Canceled)
{
isDraging = false;
Reset();
}
}
swipeDelta = Vector2.zero;
if (isDraging)
{
if (Input.touches.Length < 0)
swipeDelta = Input.touches[0].position - startTouch;
else if (Input.GetMouseButton(0))
swipeDelta = (Vector2)Input.mousePosition - startTouch;
}
if (swipeDelta.magnitude > 90)
{
float x = swipeDelta.x;
float y = swipeDelta.y;
if (Mathf.Abs(x) > Mathf.Abs(y))
{
if (x < 0)
{
swipeLeft = true;
}
else
swipeRight = true;
}
else
{
if (y < 0)
swipeDown = true;
else
swipeUp = true;
}
}
if (swipeDown && slideDone && helloEnded)
{
slideDone = false;
animator.SetTrigger("Slide");
StartCoroutine(GoSlide());
}
if (swipeUp && helloEnded && jumpDone)
{
jumpDone = false;
Reset();
animator.SetTrigger("Up");
}
Debug.Log(jumpDone);
dir = 0;
if (swipeLeft)
{
dir = -1;
}
else if (swipeRight)
{
dir = 1;
}
if (helloEnded && !isInMovement && (((dir > 0) && (mid != 1)) || (dir < 0) & (mid != -1)))
{
currentDir = dir;
currentDistance = distance;
if ((dir > 0) && (mid < 1) && (slideDone) && (jumpDone))
{
isInMovement = true;
animator.SetTrigger("Right");
mid++;
StartCoroutine(GoRight());
}
else if ((dir > 0) && (mid < 1) && (!jumpDone))
{
isInMovement = true;
mid++;
StartCoroutine(GoRight());
}
else if ((dir > 0) && (mid < 1) && (!slideDone))
{
isInMovement = true;
animator.SetTrigger("RightAfterSlide");
mid++;
StartCoroutine(GoRight());
}
if ((dir < 0) && (mid > -1) && (slideDone) && (jumpDone))
{
isInMovement = true;
animator.SetTrigger("Left");
mid--;
StartCoroutine(GoLeft());
}
else if ((dir < 0) && (mid > -1) && (!jumpDone))
{
isInMovement = true;
mid--;
StartCoroutine(GoLeft());
}
else if ((dir < 0) && (mid > -1) && (!slideDone))
{
isInMovement = true;
animator.SetTrigger("LeftAfterSlide");
mid--;
StartCoroutine(GoLeft());
}
}
}
}
IEnumerator GoLeft()
{
Reset();
while (currentDistance >= 0)
{
yield return new WaitForEndOfFrame();
float speed1 = distance / time * 2;
float tmpDist = Time.deltaTime * speed1;
animator.SetFloat("SpeedAnim", WorldController.speedOfAnim);
cc.Move(Vector3.right * currentDir * tmpDist);
currentDistance -= tmpDist;
}
if (transform.position.x > 10f)
{
transform.position = new Vector3(11f, transform.position.y, transform.position.z);
}
else if (transform.position.x > 8f)
{
transform.position = new Vector3(9.62f, transform.position.y, transform.position.z);
}
isInMovement = false;
}
IEnumerator GoRight()
{
Reset();
while (currentDistance >= 0)
{
yield return new WaitForEndOfFrame();
float speed1 = distance / time * 2;
float tmpDist = Time.deltaTime * speed1;
animator.SetFloat("SpeedAnim", WorldController.speedOfAnim);
cc.Move(Vector3.right * currentDir * tmpDist);
currentDistance -= tmpDist;
}
if (transform.position.x > 11.6f)
{
transform.position = new Vector3(12.38f, transform.position.y, transform.position.z);
}
else if (transform.position.x > 10f)
{
transform.position = new Vector3(11f, transform.position.y, transform.position.z);
}
isInMovement = false;
}
IEnumerator GoSlide()
{
Reset();
currentDistance = transform.position.y - 4.797371f;
while (currentDistance > 0)
{
yield return new WaitForEndOfFrame();
float tmpDist = Time.deltaTime * 3.5f;
cc.Move(Vector3.down * tmpDist);
currentDistance -= tmpDist;
}
slideDone = true;
jumpDone = true;
}
public void StartLevel()
{
play = true;
EnviromentMoves = true;
}
private void Reset()
{
tap = swipeDown = swipeUp = swipeLeft = swipeRight = false;
startTouch = swipeDelta = Vector2.zero;
isDraging = false;
}
void OnControllerColliderHit(ControllerColliderHit hit)
{
if (hit.gameObject.CompareTag("Ground") && k == 0 && !jumpDone && slideDone)
{
k++;
Invoke("JumpTrue", 1.25f);
}
}
private void JumpTrue()
{
jumpDone = true;
k--;
}
}

Swipe Controls for Unity runner game

I'm making a running game on android using C#. I try to do swipe control for Unity runner but code does not working properly. Sometimes when I swipe left player goes right and jumping is awful. Here is my code, I do not understand where is my mistake. sometimes it missing touches at all. Player psition is: (10, 1, 0) and the Ground (plane) position is: (10, 0, 0). Player is a simple Cylinder whith Rigidbody.
public int leftLine = 7;
public int rightLine = 13;
public int currentLine = 10;
public int distanceBetweenLines = 3;
public float xSideMoveSpeed = 50f;
public float minSwipDelta = 10f;
public float jumpSpeed = 100f;
Vector2 swipeDelta;
bool canSwipe,
RightSwipe,
LeftSwipe,
UpSwipe,
DownSwipe;
Rigidbody rb;
public float maxDistanceForJumping = 1.05f;
void Start()
{
rb = gameObject.GetComponent<Rigidbody>();
}
void Update()
{
TouchDetector();
MoveByTouch();
}
void FixedUpdate()
{
if (IsGrounded() && UpSwipe)
{
rb.AddForce(Vector3.up * jumpSpeed);
UpSwipe = false;
}
}
public bool IsGrounded()
{
return Physics.Raycast(transform.position, Vector3.down, maxDistanceForJumping);
}
void MoveByTouch()
{
if (canSwipe && RightSwipe)
{
if (currentLine < rightLine)
currentLine += distanceBetweenLines;
canSwipe = false;
swipeDelta = Vector2.zero;
}
if (canSwipe && LeftSwipe)
{
if (currentLine > leftLine)
currentLine -= distanceBetweenLines;
canSwipe = false;
swipeDelta = Vector2.zero;
}
Vector3 newPos = new Vector3(currentLine, transform.position.y, transform.position.z);
transform.position = Vector3.Lerp(transform.position, newPos, xSideMoveSpeed * Time.deltaTime);
}
void TouchDetector()
{
if (Input.touchCount > 0)
{
// can we swipe or ont
if (Input.touches[0].phase == TouchPhase.Began)
{
canSwipe = true;
}
else if (Input.touches[0].phase == TouchPhase.Canceled || Input.touches[0].phase == TouchPhase.Ended)
{
canSwipe = false;
swipeDelta = Vector2.zero;
}
if (Input.touches[0].phase == TouchPhase.Moved)
{
// Calculating delta
if (Mathf.Abs(Input.touches[0].deltaPosition.sqrMagnitude) > minSwipDelta)
swipeDelta = Input.touches[0].deltaPosition;
else
swipeDelta = Vector2.zero;
// Detecting arrows
if (Mathf.Abs(swipeDelta.x) > Mathf.Abs(swipeDelta.y) && swipeDelta.x > 0)
{
RightSwipe = true;
LeftSwipe = UpSwipe = DownSwipe = false;
}
if (Mathf.Abs(swipeDelta.x) > Mathf.Abs(swipeDelta.y) && swipeDelta.x < 0)
{
LeftSwipe = true;
RightSwipe = UpSwipe = DownSwipe = false;
}
if (Mathf.Abs(swipeDelta.x) < Mathf.Abs(swipeDelta.y) && swipeDelta.y > 0)
{
UpSwipe = true;
RightSwipe = LeftSwipe = DownSwipe = false;
}
if (Mathf.Abs(swipeDelta.x) < Mathf.Abs(swipeDelta.y) && swipeDelta.y < 0)
{
DownSwipe = true;
RightSwipe = LeftSwipe = UpSwipe = false;
}
}
}
}

Unity 2D. Add knockback effect when my player hits enemy

I'm programming 2D Platformer I had problem/issue/weird situation - name it like you want. First of all, on my base Scene I have 4 Blobs (like on picture):
View from my Scene:
The thing is: When I hit the biggest one it gets damage bo no knockback, the smaller one above got knock back effect and no damage. Every one of them are on Enemy Tag and Enemy Layer.
Funny Thing - when only one of them is on Enemy Layer and Tag, it gets correct effect (damage + knockback). Is it scripting issue or I messed something up in Unity.
PS. Another Funny Thing - when I set every Blob being on Enemy Layer and Tag. And I hit directly (and exactly) the one above me (with yellow arrow). It behaves correctly... So I'm even move confused.
My Code (Sorry it's compacted to one big file because of testing) Fighting and Moving
[PlayerControls.cs] :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using UnityEngine.Animations;
using UnityEngine.SceneManagement;
public class PlayerControls : MonoBehaviour
{
private float moveHoriz;
public float speed;
public bool grounded;
private float crouch;
public bool crouching;
private Rigidbody2D rb;
bool sliding;
public float slideTimer;
public float maxSlideTime;
public float jumpForce;
public bool facingRight = true;
public bool isDoubleJump = true;
public LayerMask whatIsGround;
public float groundRadius;
public Transform GroundCheck;
public Transform CeilingCheck;
private bool ceiled;
public Transform NearGroundCheck;
private bool isGroundNear;
private int extraJumps;
public int extraJumpValues;
private bool jumping;
private bool attack1;
private bool attack2;
private bool attack3;
private bool airAttack1;
public bool goodOrder1;
public bool goodOrder2;
public bool goodOrder3;
public bool badOrder2;
public bool badOrder3;
public bool combo;
public float comboDuration;
public float comboEndup = 1;
private bool shootBow;
public bool reloadBow = true;
public int reloadTime = 1;
public Transform attackPos;
public float attackRange;
public LayerMask whatIsEnemy;
public int damage;
private EnemyScript enemy;
public Animator animator;
// Use this for initialization
void Start()
{
extraJumps = extraJumpValues;
rb = GetComponent<Rigidbody2D>();
enemy = GameObject.FindGameObjectWithTag("Enemy").GetComponent<EnemyScript>();
}
// Update is called once per frame
void Update()
{
animator.SetFloat("Speed", Mathf.Abs(moveHoriz));
animator.SetBool("Grounded", grounded);
animator.SetFloat("vertSpeed", rb.velocity.y);
animator.SetInteger("isDoubleJump", extraJumps);
animator.SetBool("Crouch", crouching);
animator.SetBool("isSliding", sliding);
animator.SetFloat("stopSliding", slideTimer);
animator.SetBool("isGroundNear", isGroundNear);
animator.SetBool("comboAttack", combo);
animator.SetFloat("comboDuration", comboDuration);
animator.SetBool("reloadBow", reloadBow);
animator.SetFloat("reloadTime", reloadTime);
animator.SetBool("goodOrder1", goodOrder1);
animator.SetBool("goodOrder2", goodOrder2);
animator.SetBool("goodOrder3", goodOrder3);
animator.SetBool("badOrder2", badOrder2);
animator.SetBool("badOrder3", badOrder3);
moveHoriz = Input.GetAxisRaw("Horizontal");
crouch = Input.GetAxisRaw("Crouch");
RangeAttack();
OrderCheck();
Crouch();
if (grounded != true)
{
jumping = true;
sliding = false;
slideTimer = 0;
}
if (grounded == true)
{
jumping = false;
extraJumps = extraJumpValues;
}
if (Input.GetKeyDown(KeyCode.UpArrow) && extraJumps > 0)
{
jumping = true;
rb.velocity = Vector2.up * jumpForce;
extraJumps--;
}
else if (Input.GetKeyDown(KeyCode.UpArrow) && extraJumps == 0 && grounded == true)
{
rb.velocity = Vector2.up * jumpForce;
}
if (Input.GetKeyDown(KeyCode.H))
{
Die();
}
}
void FixedUpdate()
{
grounded = Physics2D.OverlapCircle(GroundCheck.position, groundRadius, whatIsGround);
ceiled = Physics2D.OverlapCircle(CeilingCheck.position, groundRadius, whatIsGround);
isGroundNear = Physics2D.OverlapCircle(NearGroundCheck.position, groundRadius, whatIsGround); ;
rb.velocity = new Vector2(moveHoriz * speed, rb.velocity.y);
Move();
Flip();
Sliding();
Combo();
HandleInput();
HandleAttacks();
DealDmg();
ResetValues();
}
void Move()
{
rb.velocity = new Vector2(moveHoriz * speed, rb.velocity.y);
}
// Flip (or better said Rotate) Character.
void Flip()
{
if ((moveHoriz < 0 && facingRight == true) || (moveHoriz > 0 && facingRight == false))
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
void Crouch()
{
if ((crouch != 0 || ceiled == true) && grounded == true)
{
crouching = true;
}
else
{
crouching = false;
}
if (crouching)
{
speed = 10;
}
else
{
speed = 15;
}
}
void Sliding()
{
//If statement to check if player is sliding to maxSlide capacity
if (Input.GetButtonDown("Crouch") && speed > 0)
{
slideTimer = 0f;
sliding = true;
if (slideTimer >= maxSlideTime && sliding == true || moveHoriz == 0)
{
sliding = false;
animator.SetBool("isSliding", false);
crouching = true;
animator.SetBool("Crouch", false);
}
}
if (slideTimer < maxSlideTime && moveHoriz == 0 && crouch > 0)
{
sliding = false;
animator.SetBool("isSliding", false);
animator.SetBool("Crouch", true);
crouching = true;
}
if (sliding)
{
speed = 25;
slideTimer += Time.deltaTime;
if (slideTimer >= maxSlideTime || jumping == true)
{
sliding = false;
animator.SetBool("isSliding", false);
speed = 15;
}
if (facingRight == true)
{
rb.velocity = Vector2.right * speed;
}
else if (facingRight != true)
{
rb.velocity = Vector2.left * speed;
}
}
}
void HandleAttacks()
{
if (attack1 == true)
{
goodOrder1 = true;
goodOrder2 = false;
goodOrder3 = false;
}
if (attack2 == true)
{
goodOrder1 = false;
goodOrder2 = true;
goodOrder3 = false;
}
if (attack3 == true)
{
goodOrder1 = false;
goodOrder2 = false;
goodOrder3 = true;
}
if (airAttack1)
{
animator.SetTrigger("airAttack1");
attackRange = 1;
}
}
private void HandleInput()
{
if (Input.GetButtonDown("Attack1"))
{
attack1 = true;
}
else if (Input.GetButtonUp("Attack1"))
{
attack1 = false;
}
if (Input.GetButtonDown("Attack2"))
{
attack2 = true;
}
else if (Input.GetButtonUp("Attack2"))
{
attack2 = false;
}
if (Input.GetButtonDown("Attack3"))
{
attack3 = true;
}
else if (Input.GetButtonUp("Attack3"))
{
attack3 = false;
}
if (grounded == false && (Input.GetButtonDown("Attack1") || Input.GetButtonDown("Attack2") || Input.GetButtonDown("Attack3")))
{
airAttack1 = true;
attack1 = false;
}
if (airAttack1 == true && grounded == true)
{
airAttack1 = false;
}
}
void OrderCheck()
{
// First sequence attack
if (grounded == true && attack1 == true && comboDuration > 0)
{
goodOrder1 = true;
}
else if (goodOrder1 != true && grounded == true && attack2 == true && comboDuration <= 0)
{
badOrder2 = true;
}
// Second sequence attack
if (grounded == true && attack2 == true && comboDuration > 0)
{
goodOrder2 = true;
}
else if (goodOrder1 != true && grounded == true && attack3 == true && comboDuration <= 0)
{
badOrder3 = true;
}
// Third sequence attack
if (grounded == true && attack3 == true && comboDuration > 0)
{
goodOrder3 = true;
}
else if (goodOrder2 != true && grounded == true && goodOrder1 != true && comboDuration > 0)
{
badOrder3 = true;
}
// Clear if badOrder's achived
if (badOrder2 == true || badOrder3 == true)
{
goodOrder1 = false;
goodOrder2 = false;
goodOrder3 = false;
}
}
void Combo()
{
if (attack1 == true)
{
comboDuration = comboEndup;
}
/*if ((goodOrder1 == true || goodOrder2 == true || goodOrder3 == true) || (badOrder2 == true || badOrder3 == true))
{
comboDuration = comboEndup;
}*/
// comboEndup = 1; - reminder
if (comboDuration > 0)
{
comboDuration -= Time.deltaTime;
combo = true;
}
if (comboDuration <= 0 || (badOrder2 == true || badOrder3 == true))
{
comboDuration = 0;
combo = false;
goodOrder1 = false;
goodOrder2 = false;
goodOrder3 = false;
badOrder2 = false;
badOrder3 = false;
}
}
void ResetValues()
{
if (badOrder2 == true || badOrder3 == true)
{
badOrder2 = false;
badOrder3 = false;
}
airAttack1 = false;
if (gameObject.GetComponent<PlayerControls>().grounded == true && airAttack1 == true)
{
airAttack1 = false;
}
}
private void RangeAttack()
{
if (grounded == true && Input.GetButtonDown("Ranged"))
{
animator.SetTrigger("shootBow");
reloadBow = false;
attack1 = false;
attack2 = false;
attack3 = false;
}
}
void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(attackPos.position, attackRange);
}
public void DealDmg()
{
if (attackPos.gameObject.activeSelf == true)
{
Collider2D[] enemiesToDamage = Physics2D.OverlapCircleAll(attackPos.position, attackRange, whatIsEnemy);
for (int i = 0; i < enemiesToDamage.Length; i++)
{
enemiesToDamage[i].GetComponent<EnemyScript>().TakeDmg(damage);
if (facingRight == true)
{
gameObject.GetComponent<EnemyScript>().EnemyRB.AddForce(transform.up * 500 + transform.right * 500);
}
else if (facingRight == false)
{
gameObject.GetComponent<EnemyScript>().EnemyRB.AddForce(transform.up * 500 + (transform.right * 500) * -1);
}
attackPos.gameObject.SetActive(false);
}
}
}
void Die()
{
SceneManager.LoadScene(0);
}
}
Enemy Movement [EnemyScript.cs]:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemyScript : MonoBehaviour {
public float speed;
public float distance;
public int health;
public bool movingRight = true;
public Transform groundDetection;
public Rigidbody2D EnemyRB;
public bool trap;
public LayerMask TrapLayer;
public Transform ColideDetector;
public float detectorRadius;
public BoxCollider2D CheckHeadBounce;
// Use this for initialization
void Start ()
{
EnemyRB = gameObject.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update ()
{
trap = Physics2D.OverlapCircle(ColideDetector.position, detectorRadius, TrapLayer);
if (health <= 0)
{
Destroy(gameObject);
}
transform.Translate(Vector2.right * speed * Time.deltaTime );
RaycastHit2D groundInfo = Physics2D.Raycast(groundDetection.position, Vector2.down, distance);
if (groundInfo.collider == false || trap == true)
{
if(movingRight == true)
{
transform.eulerAngles = new Vector3(0, -180, 0);
movingRight = false;
}
else
{
transform.eulerAngles = new Vector3(0, 0, 0);
movingRight = true;
}
}
}
public void HeadBounce()
{
}
public void TakeDmg(int damage)
{
health -= damage;
Debug.Log("damage TAKEN!");
}
}
It's a gif to show what is going on
PlayerInspector - PlayerScript
Enemy Inspector - EnemyScript
You don't use the right reference of EnemyScript inside DealDmg. In the loop, you first call TakDmg on the enemy found from OverlapCircleAll, then you call AddForce on gameObject.GetComponent<EnemyScript>().EnemyRB.
Within this context, gameObject refer to the GameObject the running script is attached to (PlayerControl.cs here). You need to apply the force on the rigidbody of the gameobject inside the collision array enemisToDamage, just like you did with TakeDmg.
Here is a possible solution.
public void DealDmg()
{
if (attackPos.gameObject.activeSelf == true)
{
Collider2D[] enemiesToDamage = Physics2D.OverlapCircleAll(attackPos.position, attackRange, whatIsEnemy);
for (int i = 0; i < enemiesToDamage.Length; i++)
{
EnemyScript enemyScript = enemiesToDamage[i].GetComponent<EnemyScript>();
enemyScript.TakeDmg(damage);
if (facingRight == true)
{
enemyScript.GetComponent<RigidBody>().AddForce(transform.up * 500 + transform.right * 500);
}
else if (facingRight == false)
{
enemyScript.GetComponent<RigidBody>().AddForce(transform.up * 500 + (transform.right * 500) * -1);
}
attackPos.gameObject.SetActive(false);
}
}
}

Touch input on mobile device

I have this script for inputting touches on the mobile device. But it activates only once, I need it to be run until I take my finger off the screen
public float speed = 3;
public Rigidbody rb;
public void MoveLeft()
{
transform.Translate(-Vector3.right * speed * Time.deltaTime);
}
public void StopMoving()
{
rb.velocity = new Vector2(0, 0);
}
public void MoveRight()
{
rb.velocity = new Vector2(-speed, 0);
}
private void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
float middle = Screen.width / 2;
if (touch.position.x < middle && touch.phase == TouchPhase.Began)
{
MoveLeft();
}
else if (touch.position.x > middle && touch.phase == TouchPhase.Began )
{
MoveRight();
}
}
else
{
StopMoving();
}
}
}
You simply need to remove the two && touch.phase == TouchPhase.Began portions. This will have the overall if-statement evaluate true as long as there is one finger on the screen.
private void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
float middle = Screen.width / 2;
if (touch.position.x < middle)
{
MoveLeft();
}
else if (touch.position.x > middle)
{
MoveRight();
}
}
else
{
StopMoving();
}
}

Categories

Resources