How to control all GameObjects in array? - c#

I have a generator which generate a ball every time I press (1) ,
each ball will be stored in Array of Gameobjects called "targetBall" , I have an AI player which repels the ball with Move() method, but the problem is the AI player see only the first ball in array which is ball [0] as shown in code , how I can make the AI player see all the generated ball (infinite balls) , I tried to use for loop but I didn't make it (note : every thing worked perfect)
void Move()
{
targetBall = GameObject.FindGameObjectsWithTag("HokeyBall");
if (targetBall[0].GetComponent<HokyBall>().ballDirection == Vector3.right)
{
ballPos = targetBall[0].transform.localPosition;
if (transform.localPosition.x < Lboundry && ballPos.x > transform.localPosition.x)
{
transform.localPosition += new Vector3(speed * Time.deltaTime, 0, 0);
}
if (transform.localPosition.x < Lboundry && ballPos.x < transform.localPosition.x)
{
transform.localPosition += new Vector3(-speed * Time.deltaTime, 0, 0);
}
}
}
and this is my attempt to find each ball generated using for loop , and give me error (cant convert "int" to "GameObject)
void Move()
{
targetBall = GameObject.FindGameObjectsWithTag("HokeyBall");
foreach (GameObject i in targetball)
{
if (targetBall[i].GetComponent<HokyBall>().ballDirection == Vector3.right)
{
ballPos = targetBall[i].transform.localPosition;
if (transform.localPosition.x < Lboundry && ballPos.x > transform.localPosition.x)
{
transform.localPosition += new Vector3(speed * Time.deltaTime, 0, 0);
}
if (transform.localPosition.x < Lboundry && ballPos.x < transform.localPosition.x)
{
transform.localPosition += new Vector3(-speed * Time.deltaTime, 0, 0);
}
}
}
}

foreach returns object from the collection, so you don't have access to that collection.
Foreach way -
void Move()
{
targetBall = GameObject.FindGameObjectsWithTag("HokeyBall");
foreach (GameObject go in targetball)
{
if (go.GetComponent<HokyBall>().ballDirection == Vector3.right)
{
ballPos = go.transform.localPosition;
if (transform.localPosition.x < Lboundry && ballPos.x > transform.localPosition.x)
{
transform.localPosition += new Vector3(speed * Time.deltaTime, 0, 0);
}
if (transform.localPosition.x < Lboundry && ballPos.x < transform.localPosition.x)
{
transform.localPosition += new Vector3(-speed * Time.deltaTime, 0, 0);
}
}
}
}
For loop -
void Move()
{
targetBall = GameObject.FindGameObjectsWithTag("HokeyBall");
for (int i = 0; i < targetBall.Length; i++)
{
if (targetBall[i].GetComponent<HokyBall>().ballDirection == Vector3.right)
{
ballPos = targetBall[i].transform.localPosition;
if (transform.localPosition.x < Lboundry && ballPos.x > transform.localPosition.x)
{
transform.localPosition += new Vector3(speed * Time.deltaTime, 0, 0);
}
if (transform.localPosition.x < Lboundry && ballPos.x < transform.localPosition.x)
{
transform.localPosition += new Vector3(-speed * Time.deltaTime, 0, 0);
}
}
}
}

Related

Manually made physics for my player, but when airborne my motion is relative to rotation. How do I fix this?

I'll start off by saying I'm very new to Unity and C# and I'm attempting my first project after following a series of youtube tutorials. I manually made physics for my player (for acceleration, airborne velocity and drag, gravity, etc), but when I jump moving forward (or any other direction for that matter), when I rotate my character (through my mouse movement) my airborne movement changes relative to my rotation rather than remaining constant (I guess since it's moving in local space?). I'd like it so my airborne velocity gets influenced by my grounded velocity (that which is influenced by WASD), but doesn't move relative to my rotation, and i keep my movement direction no matter where I look.
I've been pouring overt my code for a while but I can't figure it out.
My player is called PlayerColliderParent, it has a Character Controller attached to it, along with my script PlayerColliderParentScript.cs (which handles all physics and movement for the player).
TLDR or if that was too confusing: When my player is airborne and moving, the direction of movement changes along with the player's rotation (where I look). I'd rather the direction remained constant regardless of the rotation.
Any help is appreciated as I really want to fix this.
Here is a video of the problem occuring: https://www.youtube.com/watch?v=wpEMv059cZs
And here is PlayerColliderParentScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerColliderParentScript : MonoBehaviour
{
public Transform cameraRotation;
public Vector3 directionalInput;
public float accelerationAmount = 0.5f;
public float maxSpeed = 6f;
public float maxMoveSpeed =6f;
public Vector3 directionalSpeed;
public Vector3 airDirectionalSpeed;
public float terminalVelocity = 30f;
public float gravityStrength = 1f;
public float currentYvel;
public float airDrag;
public float maxAirSpeed;
public float jumpStrength = 1f;
Vector3 gravityController;
//Rigidbody playerBody = new Rigidbody();
CharacterController controller = new CharacterController();
//Rigidbody playerBody = new Rigidbody();
// Start is called before the first frame update
void Start()
{
//playerBody = GetComponent<Rigidbody>();
controller = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
//set acceleration factor
float accelerationFactor = (accelerationAmount * 200) * Time.deltaTime;
//rotate horizontally with camera
transform.localEulerAngles = new Vector3(0, cameraRotation.localEulerAngles.y, 0);
//JUMP or press against ground
if (controller.isGrounded == true)
{
if (Input.GetKey(KeyCode.Space))
{
currentYvel = jumpStrength;
}
else
{
currentYvel = -2f /** Time.deltaTime * 500*/;
}
}
//accelerate while movement key is held
//z axis
if (Input.GetKey(KeyCode.W))
{
directionalInput.z = 1;
if (directionalSpeed.z < maxSpeed)
{
directionalSpeed.z += accelerationFactor;
}
}
else if (Input.GetKey(KeyCode.S))
{
directionalInput.z = -1;
if (directionalSpeed.z < maxSpeed)
{
directionalSpeed.z += accelerationFactor;
}
}
else if (directionalSpeed.z > 0)
{
if (controller.isGrounded == true)
{
directionalInput.z = 0;
directionalSpeed.z -= accelerationFactor;
}
else
{
directionalSpeed.z -= airDrag * Time.deltaTime * 100;
}
}
else if (directionalSpeed.z < 0)
{
if (controller.isGrounded == true)
{
directionalInput.z = 0;
directionalSpeed.z += accelerationFactor;
}
else
{
directionalSpeed.z += airDrag * Time.deltaTime * 100;
}
}
else
{
directionalInput.z = 0;
}
//x axis
if (Input.GetKey(KeyCode.D))
{
directionalInput.x = 1;
if (directionalSpeed.x < maxSpeed)
{
directionalSpeed.x += accelerationFactor;
}
}
else if (Input.GetKey(KeyCode.A))
{
directionalInput.x = -1;
if (directionalSpeed.x < maxSpeed)
{
directionalSpeed.x += accelerationFactor;
}
}
else if (directionalSpeed.x > 0)
{
if (controller.isGrounded == true)
{
directionalInput.x = 0;
directionalSpeed.x -= accelerationFactor;
}
else
{
directionalSpeed.x -= airDrag * Time.deltaTime * 100;
}
}
else if (directionalSpeed.x < 0)
{
if (controller.isGrounded == true)
{
directionalInput.x = 0;
directionalSpeed.x += accelerationFactor;
}
else
{
directionalSpeed.x += airDrag * Time.deltaTime * 100;
}
}
else
{
directionalInput.x = 0;
}
//accelerate downwards if not grounded
if (controller.isGrounded == false)
{
if (currentYvel > -terminalVelocity)
{
currentYvel -= gravityStrength * Time.deltaTime;
}
}
//Reset gravity vecctor
gravityController = Vector3.zero;
//calculate movement velocity
Vector3 direction = directionalInput.normalized;
float velocityX = direction.x * Mathf.Round(directionalSpeed.x);
float velocityY = (currentYvel / 2) * Time.deltaTime;
float velocityZ = direction.z * Mathf.Round(directionalSpeed.z);
Vector3 velocity = new Vector3(velocityX * Time.deltaTime, velocityY, velocityZ * Time.deltaTime);
//check for sprint key
if (Input.GetKey(KeyCode.LeftShift))
{
velocity *= 1.5f;
}
//move player according to velocity
controller.Move(transform.TransformDirection(velocity));
//set airspeed the same as character velocity
airDirectionalSpeed.x = velocityX * Time.deltaTime;
airDirectionalSpeed.y = 0;
airDirectionalSpeed.z = velocityZ * Time.deltaTime;
if (airDirectionalSpeed.x > 0)
{
airDirectionalSpeed.x -= airDrag * Time.deltaTime * 100;
}
if (airDirectionalSpeed.z > 0)
{
airDirectionalSpeed.z -= airDrag * Time.deltaTime * 100;
}
airDirectionalSpeed = transform.TransformDirection(airDirectionalSpeed);
Vector3 airVelocity = new Vector3(airDirectionalSpeed.x, 0, airDirectionalSpeed.z);
Vector3 airMoveAmountX = new Vector3((airVelocity.x / 3), 0, 0);
Vector3 airMoveAmountZ = new Vector3(0, 0, (airVelocity.z / 3));
//move player according to airspeed
if (controller.isGrounded == false)
{
if (airDirectionalSpeed.x < maxAirSpeed | airDirectionalSpeed.x > -maxAirSpeed)
{
controller.Move(airMoveAmountX);
}
if (airDirectionalSpeed.z < maxAirSpeed | airDirectionalSpeed.z > -maxAirSpeed)
{
controller.Move(airMoveAmountZ);
}
}
}
}
This part smells:
void Update()
{
// (...)
if (Input.GetKey(KeyCode.D))
{
directionalInput.x = 1;
if (directionalSpeed.x < maxSpeed)
{
directionalSpeed.x += accelerationFactor;
}
}
//(...)
}
If your are not grounded, you shouldn't be responding to directional inputs and accelerating in horizontal direction. Same applies for the corresponding logic for the other 3 directional keys.
You can try to add a condition to only execute this logic if the player is grounded.

How can I stop my camera clipping through terrain?

Having a bit of a problem in Unity3D. I have a fly camera with both a box collider and rigidbody, and it still moves through my terrain, which has a terrain collider and a rigidbody. The thing is, it interacts with my capsules just fine, bounces them away and everything. Obvious this is the exact opposite of what I want ha ha...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FlyCamera : MonoBehaviour
{.
/*
Writen by Windexglow 11-13-10. Use it, edit it, steal it I don't care.
Converted to C# 27-02-13 - no credit wanted.
Simple flycam I made, since I couldn't find any others made public.
Made simple to use (drag and drop, done) for regular keyboard layout
wasd : basic movement
shift : Makes camera accelerate
space : Moves camera on X and Z axis only. So camera doesn't gain any height*/
float mainSpeed = 25.0f; //regular speed
float shiftAdd = 250.0f; //multiplied by how long shift is held. Basically running
float maxShift = 1000.0f; //Maximum speed when holdin gshift
float camSens = 0.25f; //How sensitive it with mouse
private Vector3 lastMouse = new Vector3(255, 255, 255); //kind of in the middle of the screen, rather than at the top (play)
private float totalRun = 1.0f;
void Update()
{
if (Input.GetKey(KeyCode.R))
{
transform.position = new Vector3(26f, 4f, 14f);
}
lastMouse = Input.mousePosition - lastMouse;
lastMouse = new Vector3(-lastMouse.y * camSens, lastMouse.x * camSens, 0);
lastMouse = new Vector3(transform.eulerAngles.x + lastMouse.x, transform.eulerAngles.y + lastMouse.y, 0);
transform.eulerAngles = lastMouse;
lastMouse = Input.mousePosition;
//Mouse camera angle done.
//Keyboard commands
float f = 0.0f;
Vector3 p = GetBaseInput();
if (Input.GetKey(KeyCode.LeftShift))
{
totalRun += Time.deltaTime;
p = p * totalRun * shiftAdd;
p.x = Mathf.Clamp(p.x, -maxShift, maxShift);
p.y = Mathf.Clamp(p.y, -maxShift, maxShift);
p.z = Mathf.Clamp(p.z, -maxShift, maxShift);
}
else
{
totalRun = Mathf.Clamp(totalRun * 0.5f, 1f, 1000f);
p = p * mainSpeed;
}
p = p * Time.deltaTime;
Vector3 newPosition = transform.position;
if (Input.GetKey(KeyCode.Space))
{ //If player wants to move on X and Z axis only
transform.Translate(p);
newPosition.x = transform.position.x;
newPosition.z = transform.position.z;
transform.position = newPosition;
}
else
{
transform.Translate(p);
}
}
private Vector3 GetBaseInput()
{ //returns the basic values, if it's 0 than it's not active.
Vector3 p_Velocity = new Vector3();
if (Input.GetKey(KeyCode.W))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(0, 0, 1);
}
}
}
}
if (Input.GetKey(KeyCode.S))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(0, 0, -1);
}
}
}
}
if (Input.GetKey(KeyCode.A))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(-1, 0, 0);
}
}
}
}
if (Input.GetKey(KeyCode.D))
{
if (transform.position.x > 2 && transform.position.x < 53)
{
if (transform.position.y > 0 && transform.position.y < 40)
{
if (transform.position.z > 5 && transform.position.z < 52)
{
p_Velocity += new Vector3(1, 0, 0);
}
}
}
}
return p_Velocity;
}
}
This flycam isn't mine so if it's not optimal for the use I'm looking for, please notify me about that too.
Basically you are. Transforming it not adding velocity thats why it is crossing the collider
You need to get reference of the rigidbody then add velocity to it
Then it won't cross the collider
You need to modify your code for that
Where you are transforming
Instead of transforming
You need to
Rigidbody.velocity= vector3(.....)
Never mind, I fixed the problem.
I ended up having Kinematic ticked on the box collider of the camera, so that must have messed it up.

How to fix 2D animation while player walks?

I'm trying to make my character idle, run, jump and fall. I did it, but i have bug with runing animation. While he goes left or right, he doesn't play animation "run", which called by integer "noob" with parameter "2",he plays animation "fall", which "noob" is parameter "4"
I'm using Unity 4.5.x and C# code
using UnityEngine;
using System.Collections;
public class movement : MonoBehaviour {
Rigidbody2D rb;
Animator anim;
public int jumpCount = 0;
public Camera main;
float jumpTimer = 0;
void Start () {
rb = GetComponent<Rigidbody2D> ();
anim = GetComponent<Animator>();
}
void Update () {
if (Input.GetKeyDown (KeyCode.X) && jumpCount < 2 && jumpTimer == 0) {
jump ();
jumpCount += 1;
jumpTimer = 1;
StartCoroutine("jumpTime");
}
if (rb.velocity.y > 0) {
Flip();
anim.SetInteger ("noob", 3);
}
if (rb.velocity.y < 0) {
Flip();
anim.SetInteger ("noob", 4);
}
if (Input.GetAxis ("Horizontal") == 0 && rb.velocity.y == 0) {
anim.SetInteger ("noob", 1);
}
if (rb.velocity.y == 0 && Input.GetAxis ("Horizontal") != 0) {
Flip();
anim.SetInteger("noob", 2);
}
if (rb.velocity.y == 0) {
jumpCount = 0;
}
}
void FixedUpdate(){
rb.velocity = new Vector2 (Input.GetAxis ("Horizontal") * 12f, rb.velocity.y);
}
void jump(){
rb.AddForce (transform.up * 14F, ForceMode2D.Impulse);
}
void Flip() {
if (Input.GetAxis ("Horizontal") > 0) {
transform.localRotation = Quaternion.Euler (0, 0, 0);
}
if (Input.GetAxis ("Horizontal") < 0) {
transform.localRotation = Quaternion.Euler (0, 180, 0);
}
}
IEnumerator jumpTime() {
yield return new WaitForSeconds (0.4f);
jumpTimer = 0;
}
}
I tried to do something with jumCount, jumpTimer and velocity.y, but nothing helped
I would suggested making a grounded and jumping bool, you can use this bool to determine whether your character is airbourne. Also using else if conditional statements may help here to avoid setting your value more than once. Then you can do something like this:
if (grounded && jumping) {
Flip();
anim.SetInteger ("noob", 3);
jumping = false;
}
else if (!grounded) {
Flip();
anim.SetInteger ("noob", 4);
}
else if (Input.GetAxis ("Horizontal") == 0 && grounded) {
anim.SetInteger ("noob", 1);
}
else if (grounded && Input.GetAxis ("Horizontal") != 0) {
Flip();
anim.SetInteger("noob", 2);
}

How to find which collider with same tag is touching my character firstly when multiple colliders are touching my character same time

I'm trying to figure out which collider with same tag is touching my character firstly when multiple colliders are touching my character same time.
if (col.transform.gameObject.tag == "enemy") {
hit = true;
rgd.AddForce(new Vector2(0, 2.150f), ForceMode2D.Impulse);
if (transform.position.x-col.transform.gameObject.transform.position.x < 0)
{
rgd.AddForce(-1*rgd.transform.right * 40);
}
else
{
rgd.AddForce(1*rgd.transform.right * 40);
}
if (Mathf.Approximately (angle, 0)) {
Destroy (col.transform.gameObject);
damage = 0;
} else {
damage = 25;
}
enemydamageSound.Play();
}
I solved it by adding a few code.Here is my new code:
private int jumpCount = 0;
if (col.transform.gameObject.tag == "ground")
{
isGround = true;
jumpped = true;
jumpCount = 0;
}
if (col.transform.gameObject.tag == "enemy")
{
hit = true;
if (!isGround && jumpCount == 0)
{
rgd.AddForce(new Vector2(0, 2.150f), ForceMode2D.Impulse);
jumpCount++;
}
if (transform.position.x - col.transform.gameObject.transform.position.x < 0)
{
if (jumpCount == 0)
{
rgd.AddForce(new Vector2(0, 2f), ForceMode2D.Impulse);
}
rgd.AddForce(-1 * rgd.transform.right * 40);
}
else
{
if (jumpCount == 0)
{
rgd.AddForce(new Vector2(0, 2f), ForceMode2D.Impulse);
}
rgd.AddForce(1 * rgd.transform.right * 40);
}
if (Mathf.Approximately(angle, 0))
{
Destroy(col.transform.gameObject);
damage = 0;
}
else
{
damage = 25;
}
enemydamageSound.Play();
}

How to set an initial value for UI_Knob?

I am trying to set an initial value for UI.Extensions UI_Knob
see link to UI.Extensions repo UI.Extensions bitbutcket
Through some searching I have found maybe the best way to set an initial value is to use simulated pointerEventData and pass it to the script using ExecuteEvents, since the UI_Knob script uses the mouse position to set it's value.
--BELOW IS THE CODE FOR THE UI_Knob--
/// Credit Tomasz Schelenz
/// Sourced from - https://bitbucket.org/ddreaper/unity-ui-
//ONLY ALLOW ROTATION WITH POINTER OVER THE CONTROL
public void OnPointerDown(PointerEventData eventData)
{
_canDrag = true;
}
public void OnPointerUp(PointerEventData eventData)
{
_canDrag = false;
}
public void OnPointerEnter(PointerEventData eventData)
{
_canDrag = true;
}
public void OnPointerExit(PointerEventData eventData)
{
_canDrag = true; // Now you can drag with pointer OFF control.
}
public void OnBeginDrag(PointerEventData eventData)
{
SetInitPointerData(eventData);
}
void SetInitPointerData(PointerEventData eventData)
{
_initRotation = transform.rotation;
_currentVector = eventData.position - (Vector2)transform.position;
_initAngle = Mathf.Atan2(_currentVector.y, _currentVector.x) * Mathf.Rad2Deg;
}
public void OnDrag(PointerEventData eventData)
{
//CHECK IF CAN DRAG
if (!_canDrag)
{
SetInitPointerData(eventData);
return;
}
_currentVector = eventData.position - (Vector2)transform.position;
_currentAngle = Mathf.Atan2(_currentVector.y, _currentVector.x) * Mathf.Rad2Deg;
Quaternion addRotation = Quaternion.AngleAxis(_currentAngle - _initAngle, this.transform.forward);
addRotation.eulerAngles = new Vector3(0, 0, addRotation.eulerAngles.z);
Quaternion finalRotation = _initRotation * addRotation;
if (direction == Direction.CW)
{
knobValue = 1 - (finalRotation.eulerAngles.z / 360f);
if (snapToPosition)
{
SnapToPosition(ref knobValue);
finalRotation.eulerAngles = new Vector3(0, 0, 360 - 360 * knobValue);
}
}
else
{
knobValue = (finalRotation.eulerAngles.z / 360f);
if (snapToPosition)
{
SnapToPosition(ref knobValue);
finalRotation.eulerAngles = new Vector3(0, 0, 360 * knobValue);
}
}
//PREVENT OVERROTATION
if (Mathf.Abs(knobValue - _previousValue) > 0.5f)
{
if (knobValue < 0.5f && loops > 1 && _currentLoops < loops - 1)
{
_currentLoops++;
}
else if (knobValue > 0.5f && _currentLoops >= 1)
{
_currentLoops--;
}
else
{
if (knobValue > 0.5f && _currentLoops == 0)
{
knobValue = 0;
transform.localEulerAngles = Vector3.zero;
SetInitPointerData(eventData);
InvokeEvents(knobValue + _currentLoops);
return;
}
else if (knobValue < 0.5f && _currentLoops == loops - 1)
{
knobValue = 1;
transform.localEulerAngles = Vector3.zero;
SetInitPointerData(eventData);
InvokeEvents(knobValue + _currentLoops);
return;
}
}
}
//CHECK MAX VALUE
if (maxValue > 0)
{
if (knobValue + _currentLoops > maxValue)
{
knobValue = maxValue;
float maxAngle = direction == Direction.CW ? 360f - 360f * maxValue : 360f * maxValue;
transform.localEulerAngles = new Vector3(0, 0, maxAngle);
SetInitPointerData(eventData);
InvokeEvents(knobValue);
return;
}
}
transform.rotation = finalRotation;
InvokeEvents(knobValue + _currentLoops);
_previousValue = knobValue;
}
private void SnapToPosition(ref float knobValue)
{
float snapStep = 1 / (float)snapStepsPerLoop;
float newValue = Mathf.Round(knobValue / snapStep) * snapStep;
knobValue = newValue;
}
private void InvokeEvents(float value)
{
if (clampOutput01)
value /= loops;
OnValueChanged.Invoke(value);
}
}
[System.Serializable]
public class KnobFloatValueEvent : UnityEvent<float> { }
}
I Answered my own question without using simulated mouse data. Instead, I added a Start() method with MyStartingAngle() method. See below. I chopped up the UI_Knob's method for rotation/setting value and basically just injected my own angle. I would still like to know how to perform this with simulated mouse data if anyone is willing. I would appreciate any input on my solution as well. Thanks for reading!!
// ADD THIS INTO UI_Knob script below initialization.
// I added this here to allow for setting an initial rotation/value.
void Start(){
float myFirstAngle = 180f;
MyStartingAngle (myFirstAngle);
}
void MyStartingAngle(float angle){
_initRotation = transform.rotation;
Quaternion addRotation = Quaternion.AngleAxis(angle, this.transform.forward);
addRotation.eulerAngles = new Vector3(0, 0, addRotation.eulerAngles.z);
Quaternion finalRotation = _initRotation * addRotation;
knobValue = 1 - (finalRotation.eulerAngles.z / 360f);
transform.rotation = finalRotation;
InvokeEvents(knobValue + _currentLoops);
_previousValue = knobValue;
}

Categories