Ball swiping in Augmented reality - c#

I am working on football penalty game i am using a image target for ground i have a plane put grass texture on it i have models for goal post etc for football i add a sphere and add a RigidBody to it then i add a script to it for swiping the ball the problem is that if the Grivity is checked i am unable to see my football on the ground and if gravity is unchecked i am able to see my football but without grivity when i kicked the ball i am unable to put the ball into the net ball move to sky etc.please help me to solve my problem thanks.
Here's my script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class SwipeControl : MonoBehaviour
{
//variables for swipe input detection
private Vector3 fp; //First finger position
private Vector3 lp; //Last finger position
private float dragDistance; //Distance needed for a swipe to register
//variables for determining the shot power and position
public float power; //power at which the ball is shot
private Vector3 footballPos;
//initial football position for replacing the ball at the same posiiton
private float factor = 34f;
// keep this factor constant, also used to determine force of shot
public bool canShoot = true; //flag to check if shot can be taken
public int scorePlayer = 0; //score of player
public int scoreOpponent = 0; //score of oponent
public int turn = 0; //0 for striker, 1 for goalie
public bool isGameOver = false; //flag for game over detection
Vector3 oppKickDir; //direction at which the ball is kicked by opponent
public int shotsTaken = 0; //number of rounds of penalties taken
private bool returned = true; //flag to check if the ball is returned to its initial position
public bool isKickedPlayer = false; //flag to check if the player has kicked the ball
public bool isKickedOpponent = false; //flag to check if the opponent has kicked the ball
void Start()
{
Time.timeScale = 1; //set it to 1 on start so as to overcome the effects of restarting the game by script
dragDistance = Screen.height * 20 / 100; //20% of the screen should be swiped to shoot
Physics.gravity = new Vector3(0, -20, 0); //reset the gravity of the ball to 20
footballPos = transform.position; //store the initial position of the football
}
// Update is called once per frame
void Update()
{
if (returned)
{ //check if the football is in its initial position
if (turn == 0 && !isGameOver)
{ //if its users turn to shoot and if the game is not over
playerLogic(); //call the playerLogic fucntion
}
else if (turn == 1 && !isGameOver)
{ //if its opponent's turn to shoot
opponentLogic(); //call the respective function
}
}
}
void playerLogic()
{
//Examine the touch inputs
foreach (Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Began)
{
fp = touch.position;
lp = touch.position;
}
if (touch.phase == TouchPhase.Ended)
{
lp = touch.position;
//First check if it's actually a drag
if (Mathf.Abs(lp.x - fp.x) > dragDistance || Mathf.Abs(lp.y - fp.y) > dragDistance)
{ //It's a drag
//x and y repesent force to be added in the x, y axes.
float x = (lp.x - fp.x) / Screen.height * factor;
float y = (lp.y - fp.y) / Screen.height * factor;
//Now check what direction the drag was
//First check which axis
if (Mathf.Abs(lp.x - fp.x) > Mathf.Abs(lp.y - fp.y))
{ //If the horizontal movement is greater than the vertical movement...
if ((lp.x > fp.x) && canShoot) //If the movement was to the right)
{ //Right move
GetComponent<Rigidbody>().AddForce((new Vector3(x, 10, 15)) * power);
}
else
{ //Left move
GetComponent<Rigidbody>().AddForce((new Vector3(x, 10, 15)) * power);
}
}
else
{ //the vertical movement is greater than the horizontal movement
if (lp.y > fp.y) //If the movement was up
{ //Up move
GetComponent<Rigidbody>().AddForce((new Vector3(x, y, 15)) * power);
}
else
{ //Down move
}
}
}
canShoot = false;
returned = false;
isKickedPlayer = true;
StartCoroutine(ReturnBall());
}
else
{ //It's a tap
}
}
}
IEnumerator ReturnBall()
{
yield return new WaitForSeconds(5.0f); //set a delay of 5 seconds before the ball is returned
GetComponent<Rigidbody>().velocity = Vector3.zero; //set the velocity of the ball to zero
GetComponent<Rigidbody>().angularVelocity = Vector3.zero; //set its angular vel to zero
transform.position = footballPos; //re positon it to initial position
//take turns in shooting
if (turn == 1)
turn = 0;
else if (turn == 0)
turn = 1;
canShoot = true; //set the canshoot flag to true
returned = true; //set football returned flag to true as well
}
void opponentLogic()
{
//check for screen tap
int fingerCount = 0;
foreach (Touch touch in Input.touches)
{
if (touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled)
fingerCount++;
}
//if tapped, the opponent will shoot the football after some time delay as mentioned below
if (fingerCount > 0)
{
StartCoroutine(DelayAdd()); //add delay before the ball is shot
isKickedOpponent = true; //set opponent kicked to true
shotsTaken++; //increase set of penalty taken
returned = false;
StartCoroutine(ReturnBall()); //return the ball back to its initial position
}
}
IEnumerator DelayAdd()
{
yield return new WaitForSeconds(0.2f); //I have added a delay of 0.2 seconds
oppKickDir = new Vector3(Random.Range(-4f, 4f), Random.Range(5f, 10f), Random.Range(6f, 12f)); //generate a random x and y value in the range mentioned
GetComponent<Rigidbody>().AddForce(oppKickDir, ForceMode.Impulse); //add the force
}
}

Related

2D Jumping System not working correctly - Unity 2D

I was working on my 2D game in unity and i made this system to set the character to jump, and move around, but for some reason, i can only move mid air when i was moving on the ground, but if i stand still and then jump, i can not move mid air
Further Explaination: imagine you want to pick a coin in the air, and there is an obstacle under the coin, thus you have to jump while moving forward to pick it up, my problem is that you can only move mid air, if you were moving on the floor originally, but if you jump and THEN move right or left, the system just ignores it
My code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(CapsuleCollider2D))]
public class CharacterController2D : MonoBehaviour
{
// Move player in 2D space
public float maxSpeed = 3.4f;
public float jumpHeight = 6.5f;
public float gravityScale = 1.5f;
public Camera mainCamera;
bool facingRight = true;
float moveDirection = 0;
bool isGrounded = false;
Vector3 cameraPos;
Rigidbody2D r2d;
CapsuleCollider2D mainCollider;
Transform t;
// Use this for initialization
void Start()
{
t = transform;
r2d = GetComponent<Rigidbody2D>();
mainCollider = GetComponent<CapsuleCollider2D>();
r2d.freezeRotation = true;
r2d.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
r2d.gravityScale = gravityScale;
facingRight = t.localScale.x > 0;
if (mainCamera)
{
cameraPos = mainCamera.transform.position;
}
}
// Update is called once per frame
void Update()
{
// Movement controls
if ((Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D)) && (isGrounded || Mathf.Abs(r2d.velocity.x) > 0.01f))
{
moveDirection = Input.GetKey(KeyCode.A) ? -1 : 1;
}
else
{
if (isGrounded || r2d.velocity.magnitude < 0.01f)
{
moveDirection = 0;
}
}
// Change facing direction
if (moveDirection != 0)
{
if (moveDirection > 0 && !facingRight)
{
facingRight = true;
t.localScale = new Vector3(Mathf.Abs(t.localScale.x), t.localScale.y, transform.localScale.z);
}
if (moveDirection < 0 && facingRight)
{
facingRight = false;
t.localScale = new Vector3(-Mathf.Abs(t.localScale.x), t.localScale.y, t.localScale.z);
}
}
// Jumping
if (Input.GetKeyDown(KeyCode.W) && isGrounded)
{
r2d.velocity = new Vector2(r2d.velocity.x, jumpHeight);
}
// Camera follow
if (mainCamera)
{
mainCamera.transform.position = new Vector3(t.position.x, cameraPos.y, cameraPos.z);
}
}
void FixedUpdate()
{
Bounds colliderBounds = mainCollider.bounds;
float colliderRadius = mainCollider.size.x * 0.4f * Mathf.Abs(transform.localScale.x);
Vector3 groundCheckPos = colliderBounds.min + new Vector3(colliderBounds.size.x * 1f, colliderRadius * 0.9f, 0);
// Check if player is grounded
Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheckPos, colliderRadius);
//Check if any of the overlapping colliders are not player collider, if so, set isGrounded to true
isGrounded = false;
if (colliders.Length > 0)
{
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i] != mainCollider)
{
isGrounded = true;
break;
}
}
}
// Apply movement velocity
r2d.velocity = new Vector2((moveDirection) * maxSpeed, r2d.velocity.y);
// Simple debug
Debug.DrawLine(groundCheckPos, groundCheckPos - new Vector3(0, colliderRadius, 0), isGrounded ? Color.green : Color.red);
Debug.DrawLine(groundCheckPos, groundCheckPos - new Vector3(colliderRadius, 0, 0), isGrounded ? Color.green : Color.red);
}
}```
if ((Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D)) && (isGrounded || Mathf.Abs(r2d.velocity.x) > 0.01f))
In this line you check if you are grounded isGrounded or have some horizontal velocity Mathf.Abs(r2d.velocity.x) > 0.01f.
If you have any of those you give horizontal control.
So if you are moving horizontal en then jump Mathf.Abs(r2d.velocity.x) > 0.01f is true and gives you control in the air.
But if you are standing still and the jump isGrounded is false bequase you are in the air and Mathf.Abs(r2d.velocity.x) > 0.01f is false so you cant control your jump in the air.
If you always want control in the air remove the (isGrounded || Mathf.Abs(r2d.velocity.x) > 0.01f) check

How can I rotate the capsule only on the Y?

RotateTo is call from the Update. I want it to rotate on the Y only.
now it seems like it's rotating on all axis X,Y,Z
private void RotateTo()
{
var distance = Vector3.Distance(capsule.position, curvedLinePoints[rotationIndex].transform.position);
if(distance < 0.1f)
{
rotationIndex++;
}
// Determine which direction to rotate towards
Vector3 targetDirection = curvedLinePoints[rotationIndex].transform.position -capsule.position;
// The step size is equal to speed times frame time.
float singleStep = rotationSpeed * Time.deltaTime;
// Rotate the forward vector towards the target direction by one step
Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);
// Calculate a rotation a step closer to the target and applies rotation to this object
capsule.rotation = Quaternion.LookRotation(newDirection);
}
This is the full script.
The transform is moving along g waypoints there are more than 4000 waypoints the capsule should only rotate looking each time to the next curvedLinePoint from the List curvedLinePoints.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class WaypointsFollower : MonoBehaviour
{
public float speed;
public Waypoints waypoints;
public Transform capsule;
public bool go;
public bool goForward;
public float rotationSpeed;
private int index = 0;
private int rotationIndex = 0;
private int counter = 0;
private int c = 0;
private List<GameObject> curvedLinePoints = new List<GameObject>();
public int numofposbetweenpoints;
private bool getonce;
private bool getBackwardIndexOnce = true;
private void Start()
{
waypoints = GameObject.Find("Waypoints").GetComponent<Waypoints>();
curvedLinePoints = GameObject.FindGameObjectsWithTag("Curved Line Point").ToList();
if(waypoints.moveInReverse == false)
{
goForward = true;
}
else
{
goForward = false;
}
if(goForward)
{
index = 0;
}
}
private void Update()
{
if (getonce == false)
{
numofposbetweenpoints = curvedLinePoints.Count;
getonce = true;
}
if (go == true && waypoints.lineRendererPositions.Count > 0)
{
if(goForward == false && getBackwardIndexOnce)
{
index = waypoints.lineRendererPositions.Count - 1;
getBackwardIndexOnce = false;
}
RotateTo();
Move();
}
}
private void Move()
{
Vector3 newPos = transform.position;
float distanceToTravel = speed * Time.deltaTime;
bool stillTraveling = true;
while (stillTraveling)
{
Vector3 oldPos = newPos;
// error exception out of bound on line 55 to check !!!!!
newPos = Vector3.MoveTowards(oldPos, waypoints.lineRendererPositions[index], distanceToTravel);
distanceToTravel -= Vector3.Distance(newPos, oldPos);
if (newPos == waypoints.lineRendererPositions[index]) // Vector3 comparison is approximate so this is ok
{
// when you hit a waypoint:
if (goForward)
{
bool atLastOne = index >= waypoints.lineRendererPositions.Count - 1;
if (!atLastOne)
{
index++;
counter++;
if (counter == numofposbetweenpoints)
{
c++;
counter = 0;
}
if (c == curvedLinePoints.Count - 1)
{
c = 0;
}
}
else { index--; goForward = false; }
}
else
{ // going backwards:
bool atFirstOne = index <= 0;
if (!atFirstOne)
{
index--;
counter++;
if (counter == numofposbetweenpoints)
{
c++;
counter = 0;
}
if (c == curvedLinePoints.Count - 1)
{
c = 0;
}
}
else { index++; goForward = true; }
}
}
else
{
stillTraveling = false;
}
}
transform.position = newPos;
}
private void RotateTo()
{
var distance = Vector3.Distance(capsule.position, curvedLinePoints[rotationIndex].transform.position);
if(distance < 0.1f)
{
rotationIndex++;
}
// Determine which direction to rotate towards
Vector3 targetDirection = curvedLinePoints[rotationIndex].transform.position -capsule.position;
// The step size is equal to speed times frame time.
float singleStep = rotationSpeed * Time.deltaTime;
// Rotate the forward vector towards the target direction by one step
Vector3 newDirection = Vector3.RotateTowards(capsule.forward, targetDirection, singleStep, 0.0f);
// Calculate a rotation a step closer to the target and applies rotation to this object
capsule.rotation = Quaternion.LookRotation(newDirection);
}
}
This is a screenshot of the hierarchy the platform is the moving transform in the script and the capsule is the capsule that should only rotate facing each time the next curvedLinePoint. There are over 4000 waypoints but only 10 curvedLinePoints. a bit confusing. The capsule should rotate facing each time the next curvedLinePoint while the transform is moving along the waypoints.
Screenshot
I tried this now :
private void RotateTo()
{
var distance = Vector3.Distance(capsule.position, curvedLinePoints[rotationIndex].transform.position);
if(distance < 0.1f)
{
rotationIndex++;
}
var lookPos = curvedLinePoints[rotationIndex].transform.position - capsule.position;
lookPos.y = 0;
var rotation = Quaternion.LookRotation(lookPos);
capsule.rotation = Quaternion.Slerp(capsule.rotation, rotation, Time.deltaTime * rotationSpeed);
}
and it's rotating bu when I'm looking on the capsule I don't see any of the axis pointing the next point for example in this screenshot the blue is facing to the right the green up the red more ore less down while the point it's moving to is on the left cube so the capsule rotates but why none of the axis is pointing at its direction?
Rotation
I also added eyes to the capsule on the blue axis thinking the blue axis is forward but the capsule is rotating the eyes are never facing the next target.
This screenshot is just to show the eyes on the blue axis direction.
Eyes

Player keeps rotating when going left in Unity 2d

I'm using Unity to move my player sprite in a 2D platformer where it'll go right if right key is pressed & left if left key is pressed.
The right movement is working fine, but whenever the player moves left, I'm changing the Y rotation to 180 and the player is supposed to show left animation only but it keeps rotating back and forth when going left.
See the video sample.
This is my code:
private Rigidbody2D rb;
private void FixedUpdate() {
InputManager();
}
private void InputManager()
{
float hDir = Input.GetAxis("Horizontal");
if (state != State.hurt) {
if(!anm.GetCurrentAnimatorStateInfo(0).IsTag("attack"))
{
if (hDir < 0) // Go left
{
rb.velocity = new Vector2(-speedX, rb.velocity.y);
transform.Rotate(0f, 180f, 0f);
}
else if (hDir > 0) // Go right
{
rb.velocity = new Vector2(speedX, rb.velocity.y);
transform.Rotate(0f, 0f, 0f);
}
}
}
}
How can I make my player stick to left animation when going on left? Please do not suggest changing localScale as I know it works but for shooting purpose it's best that my player rotates.
Here is a thing transform.Rotate(0,180,0); is used to rotate 180 degree in y axis each time when this line of code execute that's why you player does not stop rotating
Here is the code you can use it will stop you player rotate according to the directions
private void InputManager()
{
float hDir = Input.GetAxis("Horizontal");
if (state != State.hurt)
{
if (!anm.GetCurrentAnimatorStateInfo(0).IsTag("attack"))
{
if (hDir < 0) // Go left
{
rb.velocity = new Vector2(-speedX, rb.velocity.y);
this.transform.rotation = Quaternion.AngleAxis(180, Vector3.up);
}
else if (hDir > 0) // Go right
{
rb.velocity = new Vector2(speedX, rb.velocity.y);
this.transform.rotation = Quaternion.AngleAxis(0, Vector3.up);
}
}
}
}
You need to add a bool Variable that is checking if the player is facing right, as well as a Flip Function that flips him:
bool bFacingRight = true;
private Rigidbody2D rb;
int _switch;
private void FixedUpdate() {
InputManager();
}
private void InputManager()
{
if (state == State.hurt || anm.GetCurrentAnimatorStateInfo(0).IsTag("attack"))
return;
float hDir = Input.GetAxis("Horizontal");
// Move the character by finding the target velocity
rb.velocity = new Vector2(hDir * 10f, rb.velocity.y);
if (hDir < 0 && bFacingRight) { // Flip Left
_switch = 0;
Flip(_switch);
}
else if (hDir > 0 && !bFacingRight) { // Flip Right
_switch= 1;
Flip(_switch);
}
}
private void Flip(int swth)
{
// Switch the way the player is labelled as facing.
bFacingRight = !bFacingRight;
// Multiply the player's x local scale by -1.
switch(swth)
{
case 0:
this.transform.rotation = Quaternion.AngleAxis(180, Vector3.up);
break;
case 1:
this.transform.rotation = Quaternion.AngleAxis(0, Vector3.up);
break;
}
}

How to link long press to move script

I found this script: https://unity3d.college/2018/01/30/unity3d-ugui-hold-click-buttons/
I am using Vuforia btw.
I was wondering how to link it to my movement script.
using UnityEngine;
public class MyDragBehaviour : MonoBehaviour
{
void Update()
{
if (Input.touchCount == 1 && Input.GetTouch(0).phase ==
TouchPhase.Moved)
{
// create ray from the camera and passing through the touch
position:
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
// create a logical plane at this object's position
// and perpendicular to world Y:
Plane plane = new Plane(Vector3.up, transform.position);
float distance = 0; // this will return the distance from the camera
if (plane.Raycast(ray, out distance))
{ // if plane hit...
Vector3 pos = ray.GetPoint(distance); // get the point
transform.position = pos;
// pos has the position in the plane you've touched
}
}
}
}
The current movement script will move my object instantly to where the tap happened on screen. I would like to have it so that you have to long press the object before moving it to avoid having the object jump around on screen.
EDIT
using UnityEngine;
using UnityEngine.EventSystems;
public class MyDragBehaviour : MonoBehaviour
{
float pointerDownTimer = 0;
const float requiredHoldTime = 0.5f; //has to hold for 0.5 seconds
void Update()
{
if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
pointerDownTimer += Time.deltaTime;
if (pointerDownTimer >= requiredHoldTime)
{
pointerDownTimer = 0;
if (!EventSystem.current.IsPointerOverGameObject())
if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
// create ray from the camera and passing through the touch position:
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
// create a logical plane at this object's position
// and perpendicular to world Y:
Plane plane = new Plane(Vector3.up, transform.position);
float distance = 0; // this will return the distance from the camera
if (plane.Raycast(ray, out distance))
{ // if plane hit...
Vector3 pos = ray.GetPoint(distance); // get the point
transform.position = pos; // pos has the position in the plane you've touched
} //whatever happens when you click
}
}
else
{
pointerDownTimer = 0;
}
}
}
}
You just need to implement a simple timer, that increases when you press and resets when you release:
float pointerDownTimer = 0;
const float requiredHoldTime = 0.5f //has to hold for 0.5 seconds
void Update(){
if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
pointerDownTimer += Time.deltaTime;
if (pointerDownTimer >= requiredHoldTime){
...... //whatever happens when you click
}
} else{
pointerDownTimer = 0;
}
}

Basic C# Unity2D movement script not functioning

Hi there fellow Overflowers!
I have recently dived into C# in Unity, because I believe that it has more functionality than UnityScript, and I come from a C++ background. Referencing some code from a 2D script in the Sample Assets, I have tried to create my own. The code is below:
using UnityEngine;
public class PlayerControl : MonoBehaviour {
//Variables
[HideInInspector]
public bool facingForward = true; //for Flip() Function
bool isGround = true; //for Grounded() Function
public float maxSpeed = 5.0f; //Terminal sideways velocity
public float HorizonAxis; //Checks for a/d movement
public float jumpFloat = 1000.0f; //Modular, use Unity Editor
public float moveFloat = 400.0f; // " "
void Start() {
//transform.position(0,0,0);
}
void Flip() {
facingForward = !facingForward; //switches boolean
Vector3 theScale = transform.localScale; //assigns vector to localscale of Player
theScale.x *= -1; //if x = 1, position becomes -1 and thus flips
transform.localScale = theScale; //reassigns the localscale to update theScale
}
bool Grounded() {
if (transform.position.y > 1) { //if position of gameObject is greater that 1, not grounded
isGround = false;
} else {
isGround = true;
}
return isGround; //function returns true or false for isGround
}
void Update() {
HorizonAxis = /*UnityEngine.*/Input.GetAxis ("Horizontal"); //assigns HorizonAxis to a/d movement from UnityEngine.Input
if (HorizonAxis * rigidbody2D.velocity.x > maxSpeed) { // if Input a/d by current x velocity of gameObject is greater than maxSpeed
rigidbody2D.velocity = new Vector2 (Mathf.Sign (rigidbody2D.velocity.x) * maxSpeed, rigidbody2D.velocity.y); //1 or -1 times the max speed, depending on direction
}
else if (HorizonAxis * rigidbody2D.velocity.x < maxSpeed) { //if Input a/d is less than terminal velocity
rigidbody2D.AddForce(Vector2.right * HorizonAxis * moveFloat); //add force to the right equivilant to Input by scalar moveFloat
}
if (Input.GetButtonDown ("Jump")) { //If Space
if(isGround) { //and isGround returns true
rigidbody2D.AddForce(new Vector2(0.0f, jumpFloat)); //add upwards force to bottom of rigidbody2D
isGround = false; //Resets isGround value
}
}
if (HorizonAxis > 0 && !facingForward) {//if UnityEngine.Input is to the right and facing left
Flip (); //execute
}
else if (HorizonAxis < 0 && facingForward) { //else
Flip (); //execute
}
}
}
Unfortunately, the code just doesn't work. I get no compile errors, but any Input does not effect the current position of the character. Should I be using transform.Translate to change the position, or stick with AddForce to a Vector2 until the character hits a maxSpeed?
Thanks heaps :)
I (kinda) fixed the jerky jumping issue, basically you look for the input in the Update() function which switches a Bool in FixedUpdate()
void Update () {
if (Input.GetKeyDown (KeyCode.Space) && playerGrounded) {
playerJumped = true;
}
}
Then in FixedUpdate() I looked for this Bool and did my AddForce
void FixedUpdate () {
if (playerJumped) {
playerJumped = false;
rigidbody2D.AddForce (new Vector2 (0, jumpForce),ForceMode2D.Impulse);
playerGrounded = false;
}
}
Setting playerJumped to false makes sure it doesn't run several times and the player can't jump again because I also set the grounded to false. grounded gets set back to true when the player collides with things tagged "ground".
I'm still new to Unity and C# overall so I can't guarantee this is the best (or even a good) way. Hope I could help somehow though ;)

Categories