Unity Subway surfers collision - c#

So I been working on a game like subway surfers and I have been stuck with this problem for a while, I been trying to make a collision like subway surfers were if the player slides to the left and there is a train there, it will slow it down for a second and then make it go back to its normal speed. I have been watching this video that explains exactly on what I want to do(Video Link:https://www.youtube.com/watch?v=BcygVd2XpD4)the problem is that the tutorial has some stuff that I did not put in my game, like they made the player switch lanes using the wasd keys and wrote a different code and I wrote a different code for that, the stuff that I did differently made the whole code not work. I been searching for a different way on how to do this but I can not find any tutorials that get the exact thing I want except that one.
This is my player swipe code:https://pastebin.com/d34G2ZU3
the part on my Collison code that makes my whole code not work is when I start adding the animation. Im not sure what exactly is stopping my code from working but I know that after I add the animation code nothing works, I get no errors and nothing really happens. I used stumbtolerance, stopallstate, and stumbletime to make it so my player can stumble but when I started adding the script from the tutorial were some parts that I did not have in my swipe code that he had and he referenced it in his collision code.Im trying to make a code that checks if the player switchs lanes and if there is something there, if there is then to make the player go back to its original spot and get slown down for a bit, if he collides with the thing again he dies.
my collision code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCollisionCode : MonoBehaviour
{
public enum HitX { Left, Mid, Right, None }
public enum HitY { Up, Mid, Down, Low, None }
public enum HitZ { Forawd, Mid, Backward, None }
public HitX hitX = HitX.None;
public HitY hitY = HitY.None;
public HitZ hitZ = HitZ.None;
public bool EnemyCollide = false;
public PlayerMovement pm;
public Animator animator;
public BoxCollider boxcollider;
public bool StopAllState = false;
public float stumbtolerance = 10f;
public float stumbletime;
// Start is called before the first frame update
void Start()
{
stumbletime = stumbtolerance;
boxcollider = GetComponent<BoxCollider>();
}
// Update is called once per frame
void Update()
{
if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1)
StopAllState = false;
stumbletime = Mathf.MoveTowards(stumbletime, stumbtolerance, Time.deltaTime);
}
public HitX GetHitX(Collider other)
{
Bounds char_bounds = boxcollider.bounds;
Bounds col_bounds = other.bounds;
float min_x = Mathf.Max(col_bounds.min.x, char_bounds.min.x);
float max_x = Mathf.Min(col_bounds.max.x, char_bounds.max.x);
float average = (min_x + max_x) / 2f - col_bounds.min.x;
HitX hit;
if (average > col_bounds.size.x - 0.335)
hit = HitX.Right;
else if (average < 0.33f)
hit = HitX.Left;
else
hit = HitX.Mid;
return hit;
}
public HitY GetHitY(Collider other)
{
Bounds char_bounds = boxcollider.bounds;
Bounds col_bounds = other.bounds;
float min_y = Mathf.Max(col_bounds.min.y, char_bounds.min.y);
float max_y = Mathf.Min(col_bounds.max.y, char_bounds.max.y);
float average = ((min_y + max_y) / 2f - char_bounds.min.y) / char_bounds.size.y;
HitY hit;
if (average < 0.17f)
hit = HitY.Low;
else if (average < 0.335)
hit = HitY.Down;
else if (average < 0.33f)
hit = HitY.Mid;
else
hit = HitY.Up;
return hit;
}
public HitZ GetHitZ(Collider other)
{
Bounds char_bounds = boxcollider.bounds;
Bounds col_bounds = other.bounds;
float min_z = Mathf.Max(col_bounds.min.z, char_bounds.min.z);
float max_z = Mathf.Min(col_bounds.max.z, char_bounds.max.z);
float average = ((min_z + max_z) / 2f - char_bounds.min.z) / char_bounds.size.z;
HitZ hit;
if (average < 0.335)
hit = HitZ.Backward;
else if (average < 0.66f)
hit = HitZ.Mid;
else
hit = HitZ.Forawd;
return hit;
}
public void OnCharacterCollideHit(Collider other)
{
hitX = GetHitX(other);
hitY = GetHitY(other);
hitZ = GetHitZ(other);
if (hitZ == HitZ.Forawd && hitX == HitX.Mid)
{
if (hitY == HitY.Low)
{
PlayAnimation("360Flip");
ResetCollision();
}
else if (hitY == HitY.Down)
{
Stumble("360Flip");
}
else if (hitY == HitY.Mid)
{
if (other.tag == "Enemy")
{
ResetCollision();
StartCoroutine(DeathPlayer("CrushDeath"));
}
else if (other.tag != "Ramp")
Debug.Log("StubleCorneright");
ResetCollision();
}
else if (hitY == HitY.Up)
{
Debug.Log("StubleCorneright");
ResetCollision();
}
}
else if (hitZ == HitZ.Mid)
{
if (hitX == HitX.Right)
{
Debug.Log("StubleCorneright");
ResetCollision();
}
else if (hitX == HitX.Left)
{
}
else if (hitZ == HitZ.Mid)
{
if (hitX == HitX.Right)
{
Debug.Log("StubleCorneright");
ResetCollision();
}
else if (hitX == HitX.Left)
{
Debug.Log("StubleCorneright");
ResetCollision();
}
}else{
if (hitX == HitX.Right)
{
Debug.Log("StubleCorneright");
ResetCollision();
}
else if (hitX == HitX.Left)
{
Debug.Log("StubleCornerRight");
ResetCollision();
}
}
}
}
private void ResetCollision()
{
print(hitX.ToString() + hitY.ToString() + hitZ.ToString());
hitX = HitX.None;
hitY = HitY.None;
hitZ = HitZ.None;
}
public void PlayAnimation(string anim)
{
if (StopAllState) return;
animator.Play(anim);
}
public void Stumble(string anim)
{
animator.ForceStateNormalizedTime(0.0f);
StopAllState = true;
animator.Play(anim);
if (stumbletime < stumbtolerance / 2f)
{
StartCoroutine(DeathPlayer("CrushDeath"));
return;
}
stumbletime -= 6f;
ResetCollision();
}
public IEnumerator DeathPlayer(string anim)
{
StopAllState = true;
animator.Play(anim);
yield return new WaitForSeconds(0.2f);
}
}

So I looked at you're code for a bit and found an easy way to track how to collide with the sides, all you have to do it add another variable to check if youre finger swipes left or right, I called it public bool LeftRight = 0 then in the part you tell it to swipe left make leftRight = 1 and for Right make it = 2, After you done all that add this script
public void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Enemy" && LeftRight == 2f)
{
stopTouch = true;
targetLine--;
canitmove = false;
movec.x = -4;
LeftRight = 1;
Debug.Log("Lefts");
line = 2;
}
if (other.gameObject.tag == "Enemy" && LeftRight == 1f)
{
stopTouch = true;
targetLine++;
canitmove = false;
movec.x = 4;
LeftRight = 2;
Debug.Log("Right");
line = 0;
}
}
checks if it collides with the Enemy and witch way it swiped. With this you can add on to my code and add whatever animation you want.

Related

MissingReferenceException Error Occurs with Unity's New Input System when using "buttonEast / rightButton"

I'm getting this error in Unity after pressing the relative "eastButton":
Error: MissingReferenceException while executing 'canceled' callbacks of 'Gameplay/Block[/DualShock4GamepadHID/buttonEast,/Mouse/rightButton]'
UnityEngine.InputSystem.InputActionAsset:OnDestroy () (at Library/PackageCache/com.unity.inputsystem#1.0.2/InputSystem/Actions/InputActionAsset.cs:794)
I'm attempting to set up 'block' functionality within my game which simply locks the player's movement then disables my "canBeHit" bool which will then put the player in a state where they cannot be hit, however upon interacting with the eastButton all player movement is completely locked preventing you from moving, however rotation is still possible. Another part I'd like to note is that I'm working with the Mirror package so I can network my game, unsure if this could also be causing problems. Would really appreciate if someone could point out where I've gone wrong, I'd be very grateful.
PlayerMovementTest.cs
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using Mirror;
public class PlayerMovementTest : NetworkBehaviour
{
[Header ("Default")]
Rigidbody rb;
PlayerInput playerInput;
PlayerControls playerInputActions;
public bool isStunned;
public float stunLockTimer;
public float stunLockTimerEnd;
public Animator animations;
public ParticleSystem stunParticle;
[Header("Movement")]
public float speed;
public float baseSpeed;
[Header ("Dodge")]
public float dodgeMultiplier;
public float dodgeTimer;
public float dodgeTimerMax;
public int dodgeCheck;
public float howLongDodgeLast;
public bool isDodging;
public GameObject enemyPlayer;
public GameObject dodgeParticle;
[Header("Attack")]
public int attackReset;
public float attackTimer;
public float attackTimerResetMax;
public float attackPlayingTimerEnd;
public float lungeAttackLungeMultiplier;
public bool isAttacking;
public GameObject attackParticle;
public GameObject attackHitboxObject;
public GameObject lungeAttackHitboxObject;
[Header("Block")]
public bool canBeHit;
private void Awake()
{
playerInput = GetComponent<PlayerInput>();
rb = GetComponent<Rigidbody>();
playerInputActions = new PlayerControls();
// freezes rotation
rb.freezeRotation = true;
// enables the input controller
playerInputActions.Gameplay.Enable();
playerInputActions.Gameplay.Attack.performed += Attack;
playerInputActions.Gameplay.Attack.canceled += Attack;
playerInputActions.Gameplay.Dodge.performed += Dodge;
playerInputActions.Gameplay.Block.canceled += Block;
playerInputActions.Gameplay.Block.performed += Block;
isStunned = false;
}
public void Update()
{
if (!isLocalPlayer)
return;
// dodge timers and reset
if (dodgeCheck != 1)
dodgeTimer += Time.deltaTime;
if (dodgeTimer > dodgeTimerMax)
{
dodgeCheck += 1;
dodgeTimer = 0;
}
// turns on the slide particle when sliding
if (isDodging == true)
dodgeParticle.SetActive(enabled);
else
dodgeParticle.SetActive(false);
// sets how long the EFFECT of the dash lasts for
// not how long the player will move but how long
// they will be able to collide with another player
// and stun them
if (dodgeTimer > howLongDodgeLast)
isDodging = false;
// attack timers and reset
if (attackReset != 1)
{
attackTimer += Time.deltaTime;
}
// after a certian amount of time the player attack goes away
if (attackTimer > attackPlayingTimerEnd)
{
//attackParticle.SetActive(false);
attackHitboxObject.SetActive(false);
lungeAttackHitboxObject.SetActive(false);
}
if (attackTimer > attackTimerResetMax)
{
attackReset += 1;
attackTimer = 0;
}
// makes it so attacks dont go into the minuses
if (attackReset < 0)
attackReset = 0;
// when player gets stunned it starts a timer where they cannot do any moves
if (isStunned == true)
{
stunLockTimer += Time.deltaTime;
if (stunLockTimer > stunLockTimerEnd)
{
isStunned = false;
stunLockTimer = 0f;
speed = baseSpeed;
}
}
// chanegs between animations depending on how fast the player is moving
if (rb.velocity.magnitude > 4f)
animations.SetFloat("Walk", rb.velocity.magnitude);
if (rb.velocity.magnitude < 4f)
animations.SetFloat("Idle", rb.velocity.magnitude);
// if player is stunned then play stun particle
if (isStunned == true)
stunParticle.Play();
else
stunParticle.Stop();
//edited out the print as it got distracting
// print(rb.velocity.magnitude);
}
// for dodge stun
public void OnCollisionEnter(Collision col)
{
// if you hit a player
if( col.gameObject.tag == "Player")
{
// and in dodge, number picked just as an idea of how long the dash could last
if (dodgeTimer > .1f && dodgeTimer < 1f)
{
// sets the player hit as a gameobject that cabn be affected in script
enemyPlayer = col.gameObject;
// decreases speed (or in this case increases as i cannot test 2 players
enemyPlayer.GetComponent<PlayerMovementTest>().speed = 0;
enemyPlayer.GetComponent<PlayerMovementTest>().isStunned = true;
}
}
}
public void FixedUpdate()
{
// calls movement function
Movement();
}
public void Attack(InputAction.CallbackContext context)
{
if (attackReset == 1 && isStunned == false)
{
isAttacking = true;
attackHitboxObject.SetActive(enabled);
attackReset -= 1;
animations.SetTrigger("Attack");
attackParticle.SetActive(enabled);
}
//if (attackReset == 1 && isStunned == false)
/*
if (context.performed)
{
print("attack start");
}
if (context.canceled)
{
// for luneg attack
rb.AddForce(transform.forward * lungeAttackLungeMultiplier, ForceMode.Impulse);
isAttacking = true;
lungeAttackHitboxObject.SetActive(enabled);
attackReset -= 1;
// animations.SetTrigger("Attack");
// attackParticle.SetActive(enabled);
print("attack end");
}*/
}
public void Dodge(InputAction.CallbackContext context)
{
// checks if the player has a dodge
if (dodgeCheck == 1 && isStunned == false)
{
// used for lockign slide in place and particle effect
isDodging = true;
// adds a force to the player, spped can be adjusted with dodgeMultiplier
rb.AddForce(transform.forward * dodgeMultiplier, ForceMode.Impulse);
// removes dodge
dodgeCheck -= 1;
animations.SetTrigger("Slide");
}
}
public void Block(InputAction.CallbackContext context)
{
if (isStunned == false)
{ // when you hold the button, you lose your speed
if (context.performed)
{
canBeHit = false;
speed = 3;
animations.SetBool("Block", true);
}
// when you release it your speed goes back to normal
if (context.canceled)
{
canBeHit = true;
speed = 15;
animations.SetBool("Block", false);
}
}
}
public void Movement()
{
// used for locking slide in place, no rotation
if (isDodging == false)
{
//player movement, can only use vector2 for controller so we use a vector3
// but store the x and z in a vector 2
Vector2 inputVector = playerInputActions.Gameplay.Walk.ReadValue<Vector2>();
Vector3 tempVec = new Vector3(inputVector.x, 0, inputVector.y);
// adds force to the vector, do this seperately so we can use
//the variable for the player rotation
rb.AddForce(tempVec * speed, ForceMode.Force);
if (tempVec != Vector3.zero)
{
// finds the direction the player is moving
Quaternion targetRotation = Quaternion.LookRotation(tempVec);
// rotates players towards the way they are facing
targetRotation = Quaternion.RotateTowards(transform.rotation, targetRotation, 360 * Time.fixedDeltaTime);
rb.MoveRotation(targetRotation);
}
}
}
}
If any additional information is needed to solve my problem I'm more than happy to submit any necessary info.

Ladder climbing function in C# script for Unity won't allow the character to come off the ladder

I created a function in Unity that is supposed to allow the character to climb. It creates two problems, first of all it somehow interacts with the general movement function. When the character starts running their animation won't stop even when the player isn't moving them. Second of all the character can climb up and down the ladder but won't get off them, even though technically the logic is constructed in such a way that they should just go back to their normal state.
I have tried turning off the climb function in the Update() function so I know the running problem is caused by it, because it works fine without it.
private void Climb()
{
RaycastHit2D ladder = Physics2D.Raycast(transform.position, Vector2.up, 5, whatIsLadder);
float hDirection = Input.GetAxisRaw("Horizontal");
float vDirection = Input.GetAxisRaw("Vertical");
if (ladder.collider != null)
{
if (vDirection > 0.1f)
{
isClimbing = true;
}
}
else
{
if (hDirection > 0.1f)
{
isClimbing = false;
}
}
if (isClimbing == true && ladder.collider != null)
{
rb.gravityScale = 0;
rb.velocity = new Vector2(rb.velocity.x, climbSpeed * vDirection);
if (Mathf.Abs(vDirection) > 0.1f)
{
anim.speed = 1f;
}
else
{
anim.speed = 0f;
}
}
else
{
rb.gravityScale = naturalGravity;
}
}
I'll also give a link to the whole PlayerController script since that might help some people:
https://github.com/Pacal2/Platformer/blob/master/Assets/Scripts/PlayerController.cs
Try resetting the velocity on the rigidbody when he stops climbing, near the end of the function:
//....
{
rb.gravityScale = naturalGravity;
}
into:
{
rb.gravityScale = naturalGravity;
rb.velocity = new Vector2(0.0f, 0.0f);
}
this code also looks suspect
if (ladder.collider != null)
{
if (vDirection > 0.1f)
{
isClimbing = true;
}
}
else
{
if (hDirection > 0.1f)
{
isClimbing = false;
}
}
change to:
if (ladder.collider != null)
{
if (vDirection > 0.1f || vDirection < -0.1f) //if allowed to climb down
{
isClimbing = true;
}
if (hDirection > 0.1f || hDirection < -0.1f) //moving left
{
isClimbing = false;
}
}
for animation speed try:
anim.speed = rb.velocity.x;

How to fix movement with swipe to right and left?

I lost a lot of time trying to find what is the problem in code but I can not find the solution why my code is not triggered.
In my previous game when I implemented this code it worked perfectly, now when i implement into new game this same code for touch movement it doesn't work.
I tried to debug the code and put Debug.Log into Update method and when i swipe over screen it doesn't even get trigger.
This is the code:
int left = 0;
int right = 0;
int maxLeftCycles = 5;
int maxRightCycles = 5;
void Start()
{
//touch
left = maxLeftCycles;
right = maxRightCycles;
}
private void Update()
{
timer += Time.deltaTime;
if (Input.GetKeyUp(KeyCode.RightArrow) ||
Swipe.swipe == Swipe.SwipeDirection.right)
{
Swipe.ResetSwipe();
right = 0;
}
if (Input.GetKeyUp(KeyCode.LeftArrow) ||
Swipe.swipe == Swipe.SwipeDirection.left)
{
Swipe.ResetSwipe();
left = 0;
}
}
void FixedUpdate()
{
if (left < maxLeftCycles && !isMoving)
{
desiredPos = transform.position + Vector3.left * 1.52f;
isMoving = true;
left++;
}
if (right < maxRightCycles && !isMoving)
{
desiredPos = transform.position - Vector3.right * 1.52f;
isMoving = true;
right++;
}
if (isMoving)
{
transform.position = Vector3.MoveTowards(transform.position, desiredPos, moveSpeed * Time.deltaTime);
// this == is true if the difference between both
// vectors is smaller than 0.00001
if (transform.position == desiredPos)
{
isMoving = false;
transform.position = desiredPos;
}
}
}
I put Debug.Log in this code and in vector3.right and left but it never get triggered.
if (Input.GetKeyUp(KeyCode.RightArrow) ||
Swipe.swipe == Swipe.SwipeDirection.right)
{
Debug.Log("This is traacked");
Swipe.ResetSwipe();
right = 0;
}
if (Input.GetKeyUp(KeyCode.LeftArrow) ||
Swipe.swipe == Swipe.SwipeDirection.left)
{
Debug.Log("This is traacked");
Swipe.ResetSwipe();
left = 0;
}
This is the code for Swipe script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Swipe : MonoBehaviour
{
private float fingerStartTime = 0.0f;
private Vector2 fingerStartPos = Vector2.zero;
private bool isSwipe = false;
private float minSwipeDist = 50.0f;
private float maxSwipeTime = 0.5f;
public enum SwipeDirection
{
none,
up,
down,
right,
left
}
public static SwipeDirection swipe;
void Start()
{
swipe = SwipeDirection.none;
}
public static void ResetSwipe()
{
swipe = SwipeDirection.none;
}
// Update is called once per frame
void Update()
{
if (Input.touchCount > 0)
{
foreach (Touch touch in Input.touches)
{
switch (touch.phase)
{
case TouchPhase.Began:
/* this is a new touch */
isSwipe = true;
fingerStartTime = Time.time;
fingerStartPos = touch.position;
break;
case TouchPhase.Canceled:
/* The touch is being canceled */
isSwipe = false;
break;
case TouchPhase.Ended:
float gestureTime = Time.time - fingerStartTime;
float gestureDist = (touch.position - fingerStartPos).magnitude;
if (isSwipe && gestureTime < maxSwipeTime && gestureDist > minSwipeDist)
{
Vector2 direction = touch.position - fingerStartPos;
Vector2 swipeType = Vector2.zero;
if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
{
// the swipe is horizontal:
swipeType = Vector2.right * Mathf.Sign(direction.x);
}
else
{
// the swipe is vertical:
swipeType = Vector2.up * Mathf.Sign(direction.y);
}
if (swipeType.x != 0.0f)
{
if (swipeType.x > 0.0f)
{
// MOVE RIGHT
swipe = SwipeDirection.right;
}
else
{
// MOVE LEFT
swipe = SwipeDirection.left;
}
}
if (swipeType.y != 0.0f)
{
if (swipeType.y > 0.0f)
{
// MOVE UP
swipe = SwipeDirection.up;
}
else
{
// MOVE DOWN
swipe = SwipeDirection.down;
}
}
}
break;
}
}
}
}
}
The code in Update method for swipe input which I debug never get called or never work for me.I can not understand what i am doing wrong because the same code actually works in my previous game.
Thank you so much for reading my question I hope there will be some guy who can help me to solve this issue.
If it worked as is before hand in another project I would make sure that you are attaching the script to a game object. If it is attached to a game object make sure that it is not marked as inactive and that you aren't turning the object to inactive somewhere else in your scripts.
If neither of these are the case I would also try removing the script from the object and then reattaching it, and if that still doesn't work try deleting the object the script is attached to (if possible) and then recreate it and reattach the script.

How to Swap "rigid body" with add force in 8 direction using C#?

I am beginner of C# unity. I was searching the solution to swap cube with add force in 8 direction, but I could not find anything. I am really confused that how can I do this. Someone please guide me in this regard. Any code example or tutorial for solving the problem will be appreciated.
Thanks in advance.
Here is my code:
using UnityEngine;
using System.Collections;
public class Swaping1 : MonoBehaviour {
int swipeIndex = -1; //index of first detected swipe to prevent multiple swipes
public Vector2 startPos; //starting position of touch
public float minSwipeDist;
public float UpSwape;
public float DownSwape;
public float LeftSwape;
public float RightSwape;
public GUIButtons GUIButtonsObj;
// Use this for initialization
void Start () {
GUIButtonsObj=GetComponent<GUIButtons>();
}
public void swipe()
{
for (int i = 0; i < Input.touchCount; i++) {
Touch touch = Input.touches [i];
switch (touch.phase) {
case TouchPhase.Began:
if (swipeIndex == -1) {
swipeIndex = i;
startPos = touch.position;
}
break;
case TouchPhase.Moved:
if (i != swipeIndex)
break;
Vector2 direction = touch.position - startPos;
//vertical swipe
if (Mathf.Abs (direction.x) < Mathf.Abs (direction.y)) {
//swipe up
if ((touch.position.y - startPos.y) > minSwipeDist) {
//GUIButtonsObj.UpButton();
//transform.Translate(0f, UpSwape, 0f);
swipeIndex = -1;
}
//swipe down
else if ((touch.position.y - startPos.y) < -minSwipeDist) {
//transform.Translate(0f, -DownSwape, 0f);
//GUIButtonsObj.DownButton();
swipeIndex = -1;
}
}
//horizontal swipe
else {
//swipe right
if ((touch.position.x - startPos.x) < -minSwipeDist) {
//transform.Translate(-RightSwape, 0f, 0f);
GUIButtonsObj.LeftButton();
swipeIndex = -1;
}
//swipe left
else if ((touch.position.x - startPos.x) > minSwipeDist) {
// transform.Translate(LeftSwape, 0f, 0f);
GUIButtonsObj.RightButton();
swipeIndex = -1;
}
}
break;
}
}
}
// Update is called once per frame
void Update ()
{
swipe ();
}
}
Ok, Try this, if it works for you.
using UnityEngine;
public enum Swipes { None, Up, Down, Left, TopLeft, BottomLeft, Right, TopRight, BottomRight};
public class SwipeManager : MonoBehaviour
{
public float minSwipeLength = 200f;
Vector2 currentSwipe;
private Vector2 fingerStart;
private Vector2 fingerEnd;
public static Swipes direction;
void Update ()
{
SwipeDetection();
}
public void SwipeDetection ()
{
if (Input.GetMouseButtonDown(0)) {
fingerStart = Input.mousePosition;
fingerEnd = Input.mousePosition;
}
if(Input.GetMouseButton(0)) {
fingerEnd = Input.mousePosition;
currentSwipe = new Vector2 (fingerEnd.x - fingerStart.x, fingerEnd.y - fingerStart.y);
// Make sure it was a legit swipe, not a tap
if (currentSwipe.magnitude < minSwipeLength) {
direction = Swipes.None;
return;
}
float angle = (Mathf.Atan2(currentSwipe.y, currentSwipe.x) / (Mathf.PI));
Debug.Log(angle);
// Swipe up
if (angle>0.375f && angle<0.625f) {
direction = Swipes.Up;
Debug.Log ("Up");
// Swipe down
} else if (angle<-0.375f && angle>-0.625f) {
direction = Swipes.Down;
Debug.Log ("Down");
// Swipe left
} else if (angle<-0.875f || angle>0.875f) {
direction = Swipes.Left;
Debug.Log ("Left");
// Swipe right
} else if (angle>-0.125f && angle<0.125f) {
direction = Swipes.Right;
Debug.Log ("Right");
}
else if(angle>0.125f && angle<0.375f){
direction = Swipes.TopRight;
Debug.Log ("top right");
}
else if(angle>0.625f && angle<0.875f){
direction = Swipes.TopLeft;
Debug.Log ("top left");
}
else if(angle<-0.125f && angle>-0.375f){
direction = Swipes.BottomRight;
Debug.Log ("bottom right");
}
else if(angle<-0.625f && angle>-0.875f){
direction = Swipes.BottomLeft;
Debug.Log ("bottom left");
}
}
if(Input.GetMouseButtonUp(0)) {
direction = Swipes.None;
}
}
}

Only one gameobject being affected by script

Making a state machine AI "game" I have 3 states Movement, Combat, and View. They all work very well, now I'm making a flee (by the way if anyone has any good links to tutorials or info that they have off hand I would love that) state so I want to make all three previous state in their Idle mode. Which works perfectly when I have 1 AI. As soon as I put the rest (there is 6 total now) it will still only affect 1, but then after some time it will "release" I guess it the best term the script and just goes back to the three states that are supposed to be idle. I think that in my Coin script I am saying find and I think it needs to be something else, I'm just not sure if that's even right but based off of my previous experiences that's usually the case with Unity. I'll post some code, but here's some info that may help your eyes by not having to read through everything:
-I have a bool set up in my AIClass that is false until one of my gameobjects collides with a 'coin', and coin is jsut a gameobject i put in my game to test out my AI behaviors. When that bool is true, in my update in my AIClass(sorry it's at the very bottom of the script you can scroll down, but I had to put other code just in case I was doing something in that to cause my problem.) It sets the state of MovementState to Idle, CombatState to Idle and ViewState to Idle.
-Also, when that bool is false is the only time that the call for the transition of states occur. For example, normally the AI will search around trying to find player, if they find him they go near him, and if they are in a certain distance they fire. Pretty simple. The movement between those states happens at the end of each IENumerator when the 'NextMovementState()' or 'NextCombatState()' or 'NextViewState()' are called. So when the bool is true those should never be called, halting the AI from moving to another state other than Idle (to what it's set at when the bool is true in the update).
And this works fine when I have only 1 AI in the game.
CoinScript.cs
using UnityEngine;
using System.Collections;
public class CoinScript : MonoBehaviour {
private AIClass a;
// Use this for initialization
void Start () {
a = GameObject.Find ("Enemy").GetComponent<AIClass>();
}
// Update is called once per frame
void Update () {
}
void OnCollisionEnter(Collision collision)
{
if (collision.collider)
{
if(collision.gameObject.tag == "Enemy" || collision.gameObject.tag == "EnemyProjectile")
{
Physics.IgnoreCollision(rigidbody.collider,collision.collider);
//Debug.Log ("Enemy");
}
if(collision.gameObject.tag == "Player")
{
Debug.Log ("triggered!");
a.fleeBool = true;
Destroy(gameObject);
}
}
}
}
AIClass.cs
using UnityEngine;
using System.Collections;
public class AIClass : MonoBehaviour
{
public NavMeshAgent agent;
//Ammo in gun before reloading is required
public int ammo = 30;
public int maxAmmo = 30;
//Number of bullets a gun fires in sequence on 1 trigger pull
public int chamber = 3;
public int maxChamber = 3;
//Pause between bursts or mouse presses, set to 0 for fully automatic
public double chamberTime = 120;
//How fast a gun fires in RPS
public int fireRate = 7;
public int fireTimer = 0;
//How fast a gun can reload
public int reloadTime = 3;
public int reloadTimer = 0;
//Number of bullets fired per shot
public int bulletsFired = 1;
public GameObject bulletClone;
//Acceptable degrees as to which the AI will begin firing at its target
public int firingAngle = 5;
//Vision cone of degrees to left and right
public int visionAngle = 35;
public int visionDistance = 100;
public int vRotationSpeed = 3;
public int vIdleTimer = 0;
public int vIdleTime = 300;
public int searchTimer = 0;
public int searchTime = 300;
public int mIdleTimer = 0;
public int mIdleTime = 300;
public bool isFocusedOnPlayer = false;
public bool seesPlayer = false;
//
public bool fleeBool;
public bool flee;
public enum MovementState
{
MSearch,
MMoving,
MIdle,
}
public enum CombatState
{
CFiring,
CReloading,
CIdle,
}
public enum ViewState
{
VSearch,
VFocus,
VIdle,
}
public enum FleeState
{
FSearch,
FMoving,
FIdle
}
public CombatState combatState;
public ViewState viewState;
public MovementState movementState;
public FleeState fleeState;
//Search state (knows where player is and will head to the player's location)
IEnumerator MSearchState ()
{
mIdleTimer = 0;
int stuckTimer = 0;
while (movementState == MovementState.MSearch)
{
//I've arrived at my location, if idle too long, then go back to idle state
if(Vector3.Distance(transform.position,agent.destination) < 3)
mIdleTimer++;
//I'm stuck and haven't moved in a while, go back to idle state
if(agent.velocity.magnitude < 1)
stuckTimer++;
if(seesPlayer || mIdleTimer > mIdleTime + 200 || stuckTimer > 300)
{
agent.destination = transform.position;
movementState = MovementState.MIdle;
}
yield return 0;
}
if (!flee) {
NextMovementState();
}
}
//Wander state
IEnumerator MMovingState ()
{
while (movementState == MovementState.MMoving)
{
//Wander code... Create a random angle and convert it to radians
float randomAngle = (float)(3.14/180)*Random.Range(0,360);
//Normalize direction vector, as we will be using it to calculate where we place the circle
Vector3 tempV = agent.velocity;
Vector3.Normalize (tempV);
//Using our relative position, 5 units in front of us. Use the generated angle to find the point on the circle that we want to go to
agent.destination = transform.position + tempV * 3 + new Vector3(Mathf.Cos (randomAngle)*3,0,Mathf.Sin (randomAngle)*3);
//Check to see if we are within the arena bounds, if not, push our projected vector back inside
if(agent.destination.x > 24)
agent.destination = agent.destination + new Vector3(-7,0,0);
if(agent.destination.x < -24)
agent.destination = agent.destination + new Vector3(7,0,0);
if(agent.destination.z > 24)
agent.destination = agent.destination + new Vector3(0,0,-7);
if(agent.destination.z < -24)
agent.destination = agent.destination + new Vector3(0,0,7);
if(seesPlayer)
{
agent.destination = transform.position;
movementState = MovementState.MIdle;
}
yield return 0;
}
if (!flee) {
NextMovementState ();
}
}
//Not moving, if I don't see the player for awhile, then go wander
IEnumerator MIdleState ()
{
mIdleTimer = 0;
while (movementState == MovementState.MIdle)
{
if(seesPlayer)
mIdleTimer = 0;
else
mIdleTimer++;
if(mIdleTimer > mIdleTime + Random.Range (-100,100))
movementState = MovementState.MMoving;
yield return 0;
}
if (!flee) {
NextMovementState ();
}
}
//Visual search state, randomly look around and check to see if we see the player
IEnumerator VSearchState ()
{
Transform target = GameObject.FindWithTag ("Player").transform;
Vector3 targetPosition = target.position;
while (viewState == ViewState.VSearch)
{
searchTimer--;
//Vision Cone calculation
Vector3 targetDir = target.position - transform.position;
Vector3 forward = transform.forward;
float angle = Vector3.Angle(targetDir, forward);
//If player is within vision cone then proceed
if (angle < visionAngle)
{
//Check to see if there are any object between player and myself
RaycastHit hit;
if (Physics.Raycast(transform.position, targetDir, out hit))
{
if(hit.transform == target)
{
seesPlayer = true;
viewState = ViewState.VFocus;
}
}
}
//Look in another direction
if(searchTimer < 0)
{
searchTimer = searchTime + Random.Range (-100,100);
targetPosition = new Vector3(Random.Range (-100,100),transform.position.y,Random.Range (-100,100));
}
transform.rotation = Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(targetPosition - transform.position), vRotationSpeed*Time.deltaTime);
yield return 0;
}
if (!flee) {
NextViewState ();
}
}
//Focus on player
IEnumerator VFocusState ()
{
Transform target = GameObject.FindWithTag ("Player").transform;
while (viewState == ViewState.VFocus)
{
//Vision Cone calculation
Vector3 targetDir = target.position - transform.position;
Vector3 forward = transform.forward;
float angle = Vector3.Angle(targetDir, forward);
if (angle > visionAngle)
viewState = ViewState.VIdle;
else
{
RaycastHit hit;
//Check if there are any objects in the way
if (Physics.Raycast(transform.position, targetDir, out hit))
{
if(hit.transform == target)
{
//Tell other AI where player is
GameObject[] objArray = GameObject.FindGameObjectsWithTag ("Enemy");
AIClass[] enemyArray = new AIClass[objArray.Length];
for(int i = 0; i < enemyArray.Length; i++)
{
enemyArray[i] = (AIClass)objArray[i].GetComponent(typeof(AIClass));
if(i >= enemyArray.Length/2)
enemyArray[i].agent.destination = target.position;
else
enemyArray[i].agent.destination = target.position + target.forward*5;
enemyArray[i].movementState = MovementState.MSearch;
}
seesPlayer = true;
transform.rotation = Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(target.position - transform.position), vRotationSpeed*Time.deltaTime);
//Check to see player is within sights of the gun
if (angle < firingAngle)
isFocusedOnPlayer = true;
else
isFocusedOnPlayer = false;
}
else
{
//I no longer see the player
seesPlayer = false;
viewState = ViewState.VIdle;
isFocusedOnPlayer = false;
}
}
}
yield return 0;
}
if (!flee) {
NextViewState ();
}
}
//Visual idle state, basically the ai is just looking forward
IEnumerator VIdleState ()
{
vIdleTimer = 0;
Transform target = GameObject.FindWithTag ("Player").transform;
while (viewState == ViewState.VIdle)
{
//Vision cone calculation
vIdleTimer++;
Vector3 targetDir = target.position - transform.position;
Vector3 forward = transform.forward;
float angle = Vector3.Angle(targetDir, forward);
//Check to see if there is an object is between the ai and the player
if (angle < visionAngle)
{
RaycastHit hit;
if (Physics.Raycast(transform.position, targetDir, out hit))
{
if(hit.transform == target)
{
seesPlayer = true;
viewState = ViewState.VFocus;
}
}
}
if(vIdleTimer > vIdleTime)
viewState = ViewState.VSearch;
yield return 0;
}
if (!flee) {
NextViewState ();
}
}
//Firing gun state
IEnumerator CFiringState ()
{
while (combatState == CombatState.CFiring)
{
if(!isFocusedOnPlayer)
combatState = CombatState.CIdle;
fireTimer--;
if(ammo > 0)
{
if(chamber > 0)
{
if(fireTimer <= 0)
{
for(int i = 0; i < bulletsFired;i++)
{
GameObject temp = (GameObject) Instantiate (bulletClone,transform.position + transform.forward,transform.rotation);
temp.rigidbody.AddForce(transform.forward*500);
}
fireTimer = 60 / fireRate;
ammo--;
chamber--;
}
}
else
{
chamber = maxChamber;
fireTimer = (int)(60/chamberTime);
}
}
else
{
combatState = CombatState.CReloading;
}
yield return 0;
}
if (!flee) {
NextCombatState ();
}
}
IEnumerator CReloadingState ()
{
reloadTimer = reloadTime * 60;
while (combatState == CombatState.CReloading)
{
reloadTimer--;
if(reloadTimer <= 0)
{
ammo = maxAmmo;
combatState = CombatState.CIdle;
}
yield return 0;
}
if (!flee) {
NextCombatState ();
}
}
IEnumerator CIdleState ()
{
while (combatState == CombatState.CIdle)
{
if(isFocusedOnPlayer)
combatState = CombatState.CFiring;
yield return 0;
}
if (!flee) {
NextCombatState ();
}
}
void Start ()
{
fleeBool = false;
flee = false;
NextCombatState();
NextViewState();
NextMovementState();
}
void NextMovementState()
{
string methodName = movementState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void NextCombatState ()
{
string methodName = combatState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void NextViewState ()
{
string methodName = viewState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void NextFleeState()
{
string methodName = viewState.ToString() + "State";
System.Reflection.MethodInfo info = GetType().GetMethod(methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
StartCoroutine((IEnumerator)info.Invoke(this, null));
}
void Update()
{
Debug.DrawLine(transform.position, transform.position+transform.forward*5, Color.red);
if (fleeBool == true)
{
flee = true;
}
if (flee == true)
{
Debug.Log ("flee is true");
combatState = CombatState.CIdle;
movementState = MovementState.MIdle;
viewState = ViewState.VIdle;
Debug.Log ("End of idles");
}
}
}
You can use GameObject.FindObjectsOfType() or GameObject.FindGameObjectsWithTag
you can do that with store all the AIClass into array and then loop it become specific, so every enemy can affected
AIClass[] AIObject = GameObject.Find("Enemy").GetComponents<AIClass>();
foreach(AIClass a in AIObject ){
//do something with a
}
it should work.

Categories