How to create a score multiplier? - c#

I am a making an endless skiing game, and already have a scoring system, however i want to add a score multiplier based on the number of consecutive tricks done without touching the ground. here's my script so far:
public class tricksScore : MonoBehaviour
{
private float flips = 0;
private float deltaRotation = 0;
private float currentRotation = 0;
private float WindupRotation = 0;
public static Rigidbody2D rigbod;
public Text scores;
private int trickscore;
private int iflip;
private int oldscore;
private int incInScore;
public float speed;
private float counter;
private int flipscore;
private int rockDestroy;
private bool grounded;
private int multiplier = 1;
// Collision2D coll;
// Start is called before the first frame update
void Start()
{
speed = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>().speed;
scores = GameObject.Find("score").GetComponent<Text>();
rigbod = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody2D>();
grounded = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>().grounded;
}
// Update is called once per frame
void Update()
{
rigbod.velocity = new Vector2(speed, rigbod.velocity.y);
deltaRotation = currentRotation - rigbod.transform.eulerAngles.z;
currentRotation = rigbod.transform.eulerAngles.z;
if (deltaRotation >= 300) deltaRotation -= 360;
if (deltaRotation <= -300) deltaRotation += 360;
WindupRotation += (deltaRotation);
flips = WindupRotation / 340;
iflip = (int)flips;
iflip = iflip * -1;
flipscore = iflip * 10;
trickscore = flipscore + rockDestroy;
scores.text = "score " + (trickscore * multiplier);
incInScore = trickscore - oldscore;
if (incInScore >= 10)
{
oldscore = trickscore;
}
//speed += (Mathf.Round(incInScore)) / 100.0f;
if (incInScore > 1 && incInScore <= 10)
{
speed = speed + 0.15f;
counter += 3f;
}
if (incInScore > 10 && incInScore <= 20)
{
speed = speed + 0.25f;
counter += 3f;
}
if (incInScore > 20 && incInScore <= 50)
{
speed = speed + 0.50f;
counter += 3f;
}
if (incInScore > 50 && incInScore <= 100)
{
speed = speed + 0.75f;
counter += 3f;
}
if (incInScore > 100 && incInScore <= 200)
{
speed = speed + 1f;
counter += 3.5f;
}
if (incInScore > 200)
{
speed = speed + 2f;
counter += 4f;
}
if (incInScore > 5 && grounded == false)
{
multiplier = multiplier + 1;
}
else if (grounded == true)
{
multiplier = 1;
}
if (speed > 5.15f)
{
speed -= 0.05f * Time.deltaTime;
}
else if (speed == 5.15f)
{
speed = 5.15f;
}
counter -= 1.0f * Time.deltaTime;
if (counter < 0)
{
counter = 0;
}
if (incInScore >= 10)
{
incInScore = 0;
}
if (incInScore < 0)
{
incInScore = incInScore * -1;
}
}
private void OnCollisionEnter2D(Collision2D coll)
{
//counter = GameObject.FindGameObjectWithTag("Player").GetComponent<tricksScore>().counter;
if (counter > 0)
{
if (coll.collider.tag == "rock")
{
Destroy(coll.gameObject);
speed = speed + 0.15f;
rockDestroy = rockDestroy + 5;
counter = counter + 2f;
}
}
}
}
I know the scripts dirty, but hopefully its still comprehensible for you all. thanks in advance for the help.

Your ground boolean is only set in start, so it will almost always be false. Add the check statement in the update function, as when you set a variable with this property, it will only take the value at that time, it will not automatically update.

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 to implement a score combo system in endless runner gamme

this is the 3rd time asking this question and ill try to be more clear this time. I am making an endless skiing game in unity and want to make a combo/score multiplier system (similar to as seen in ski safari & alto). Basically, i want the combo counter/multiplier to increase for each trick performed while not touching the ground and then multiply it with the score of the trick performed. But in my game after the player performs a trick, the multiplier keeps increasing endlessly instead of just increasing by 1. Please check my code and help me fix this.
public class tricksScore : MonoBehaviour
{
private float flips = 0;
private float deltaRotation = 0;
private float currentRotation = 0;
private float WindupRotation = 0;
public static Rigidbody2D rigbod;
public Text scores;
private int trickscore;
private int iflip;
private int oldscore;
private int incInScore;
public float speed;
private float counter;
private int flipscore;
private int rockDestroy;
private bool grounded;
private int multiplier = 1;
private int displayScore;
// private bool isScore5 = false;
//private int timesScoreInc = 0;
// Collision2D coll;
// Start is called before the first frame update
void Start()
{
speed = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>().speed;
scores = GameObject.Find("score").GetComponent<Text>();
rigbod = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody2D>();
grounded = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>().grounded;
}
// Update is called once per frame
void Update()
{
grounded = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>().grounded;
rigbod.velocity = new Vector2(speed, rigbod.velocity.y);
deltaRotation = currentRotation - rigbod.transform.eulerAngles.z;
currentRotation = rigbod.transform.eulerAngles.z;
if (deltaRotation >= 300)
deltaRotation -= 360;
if (deltaRotation <= -300)
deltaRotation += 360;
WindupRotation += (deltaRotation);
flips = WindupRotation / 340;
iflip = (int)flips;
iflip = iflip * -1;
flipscore = (iflip * 10);
trickscore = (flipscore + rockDestroy) * multiplier;
displayScore = displayScore + trickscore;
scores.text = "score " + displayScore;
incInScore = trickscore - oldscore;
/* if (incInScore >= 5)
{
isScore5 = true;
}*/
if (incInScore >= 5)
{
oldscore = trickscore;
}
//speed += (Mathf.Round(incInScore)) / 100.0f;
if (incInScore > 1 && incInScore <= 10)
{
speed = speed + 0.15f;
counter += 3f;
}
if (incInScore > 10 && incInScore <= 20)
{
speed = speed + 0.25f;
counter += 3f;
}
if (incInScore > 20 && incInScore <= 50)
{
speed = speed + 0.50f;
counter += 3f;
}
if (incInScore > 50 && incInScore <= 100)
{
speed = speed + 0.75f;
counter += 3f;
}
if (incInScore > 100 && incInScore <= 200)
{
speed = speed + 1f;
counter += 3.5f;
}
if (incInScore > 200)
{
speed = speed + 2f;
counter += 4f;
}
/* if ( grounded == false)
{
multiplier = timesScoreInc + 1;
}*/
if ( incInScore >= 5 && grounded == false)
{
multiplier = multiplier + 1;
}
if (grounded == true)
{
multiplier = 1;
}
Debug.Log(multiplier);
if (speed > 5.15f)
{
speed -= 0.05f * Time.deltaTime;
}
else if (speed == 5.15f)
{
speed = 5.15f;
}
counter -= 1.0f * Time.deltaTime;
if (counter < 0)
{
counter = 0;
}
oldscore = 0;
trickscore = 0;
flips = 0;
flipscore = 0;
iflip = 0;
rockDestroy = 0;
incInScore = 0;
if (incInScore < 0)
{
incInScore = incInScore * -1;
}
}
private void OnCollisionEnter2D(Collision2D coll)
{
if (counter > 0)
{
if (coll.collider.tag == "rock")
{
Destroy(coll.gameObject);
speed = speed + 0.15f;
rockDestroy = (rockDestroy + 5);
counter = counter + 2f;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class tricksScore : MonoBehaviour{
private GameObject player;//get the player in start so you don't have to look for it during the update
private float deltaRotation = 5;//give the player a few degrees
private Quaternion oldRotation;//use quaternions so you don't have to account for the euler overflow
public static Rigidbody2D rigbod;
public Text scores;
private int trickscore;
private int iflip;
private int incInScore;
public float speed;
private float counter;
private int flipscore;
private int rockDestroy;
private bool grounded;
private int multiplier = 1;
private int displayScore;
// Start is called before the first frame update
void Start(){
player = GameObject.FindGameObjectWithTag ("Player");
scores = GameObject.Find("score").GetComponent<Text>();
rigbod = player.GetComponent<Rigidbody2D>();
oldRotation = rigbod.transform.rotation;
}
// Update is called once per frame
void Update(){
grounded = player.GetComponent<PlayerController> ().grounded;
speed = player.GetComponent<PlayerController> ().speed;
rigbod.velocity = new Vector2 (speed, rigbod.velocity.y);
deltaRotation += Mathf.Abs (Quaternion.Angle (rigbod.transform.rotation, oldRotation));//accumulate the absolute value of the current rotation
oldRotation = rigbod.transform.rotation;//save current rotation as old
iflip = Mathf.FloorToInt (deltaRotation / 360);//check to see how many flips have been done
deltaRotation -= iflip * 360;//subtract the flips from the current rotation so they're only counted once
flipscore = (iflip * 10);
trickscore = (flipscore + rockDestroy) * multiplier;
rockDestroy = 0;//have to reset this so its only counted once
displayScore = displayScore + trickscore;
scores.text = "score " + displayScore;
incInScore += trickscore;
if (trickscore>0){//only increase speed/multiplier if a trick has been performed
if (incInScore > 1 && incInScore <= 10) {
speed += 0.15f;
counter += 3f;
}
if (incInScore > 10 && incInScore <= 20) {
speed += 0.25f;
counter += 3f;
}
if (incInScore > 20 && incInScore <= 50) {
speed += 0.50f;
counter += 3f;
}
if (incInScore > 50 && incInScore <= 100) {
speed += 0.75f;
counter += 3f;
}
if (incInScore > 100 && incInScore <= 200) {
speed += 1f;
counter += 3.5f;
}
if (incInScore > 200) {
speed += 2f;
counter += 4f;
}
if (incInScore >= 5)
multiplier++;
}
if (grounded){
incInScore = 0;
multiplier = 1;
deltaRotation=5;
oldRotation = rigbod.transform.rotation;
}
if (speed > 5.15f)
speed -= 0.05f * Time.deltaTime;
else if (speed < 5.15f)
speed = 5.15f;
counter -= 1.0f * Time.deltaTime;
if (counter < 0)
counter = 0;
player.GetComponent<PlayerController> ().speed = speed;//update the players speed
}
private void OnCollisionEnter2D(Collision2D coll){
if (counter > 0){
if (coll.collider.tag == "rock"){
Destroy(coll.gameObject);
player.GetComponent<PlayerController> ().speed += 0.15f;//be sure to update players speed
rockDestroy +=5;
counter += 2f;
}
}
}
}

increase player speed based on score (endless skiing game)

i am am making an endless skiing game, similar to alto and ski safari, and need help in increasing the speed of my player based on the score of the tricks (backflips, etc) he has performed. Here's the code I've written so far:
(this script calculates the score of the player based on backflip)
public class tricksScore : MonoBehaviour
{
private float flips = 0;
private float deltaRotation = 0;
private float currentRotation = 0;
private float WindupRotation = 0;
public static Rigidbody2D rigbod;
float divideByNum = 0.25f;
public Text scores;
public int trickscore;
private int iflip;
// Start is called before the first frame update
void Start()
{
scores = GetComponent<Text>();
}
// Update is called once per frame
void Update()
{
deltaRotation = (currentRotation - rigbod.transform.eulerAngles.z);
currentRotation = rigbod.transform.eulerAngles.z;
if (deltaRotation >= 300)
deltaRotation -= 360;
if (deltaRotation <= -300)
deltaRotation += 360;
WindupRotation += (deltaRotation);
flips = WindupRotation / 340;
iflip = (int)flips;
iflip = iflip * -1;
trickscore = iflip * 10;
Debug.Log(trickscore);
scores.text = "score " + trickscore;
}
}
i import the variable trickscore to the script responsible for character movement:
[SerializeField] private tricksScore trickscript;
public int trickscore;
public int oldScore = 0;
public int incInScore;
trickscore = trickscript.trickscore;
incInScore = trickscript.trickscore - oldScore;
if (incInScore >= 10)
{
oldScore = trickscript.trickscore;
}
if (incInScore > 1 && incInScore <= 10)
{
speed = speed + 10.15f;
}
else if (incInScore > 10 && incInScore <= 20)
{
speed = speed + 0.25f;
}
else if (incInScore > 20 && incInScore <= 50)
{
speed = speed + 0.50f;
}
else if (incInScore > 50 && incInScore <= 100)
{
speed = speed + 0.75f;
}
else if (incInScore > 100 && incInScore <= 200)
{
speed = speed + 1f;
}
else if (incInScore > 200)
{
speed = speed + 2f;
}
the problem is that the speed of the player doesnt increase when i perform a backflip, also i think the variable that stores the score of the player (trickscore) also has broken because prior to writing the script, it used to display the players score in the console (debug.log) and in the text object ("scores") but neither happens anymore. i am a complete code noobie and this is the first game i am making , and this porblem has had the entire development stuck for a many days, so i will greatly appreciate any and all help. Thank you
my guess is that you have both scripts attached to your gameobject, the ideal would be separate the calculations and have 1 script handling it, get used to that and you will save yourself a lot of bugs (way better than pass scripts around and have a lot of confusion), an example in one file (that also should work if your player "currentSpeed" is used):
using UnityEngine;
using UnityEngine.UI;
public class tricksScore : MonoBehaviour
{
private float flips = 0;
private float deltaRotation = 0;
private float currentRotation = 0;
private float WindupRotation = 0;
public static Rigidbody2D rigbod;
float divideByNum = 0.25f;
public Text scores;
public int trickscore;
private int iflip;
public int oldScore = 0;
public int incInScore;
public float currentSpeed;
// Start is called before the first frame update
void Start()
{
scores = GetComponent<Text>();
}
// Update is called once per frame
void Update()
{
deltaRotation = (currentRotation - rigbod.transform.eulerAngles.z);
currentRotation = rigbod.transform.eulerAngles.z;
if (deltaRotation >= 300)
deltaRotation -= 360;
if (deltaRotation <= -300)
deltaRotation += 360;
WindupRotation += (deltaRotation);
flips = WindupRotation / 340;
iflip = (int)flips;
iflip = iflip * -1;
trickscore = iflip * 10;
currentSpeed += Calculations.CalculateSpeed(trickscore,oldScore);
}
}
//this should be in a separate file
public class Calculations
{
public static float CalculateSpeed(float currentScore, float oldScore)
{
var incInScore = currentScore - oldScore;
if (incInScore > 1 && incInScore <= 10)
{
return 10.15f;
}
else if (incInScore > 10 && incInScore <= 20)
{
return 0.25f;
}
else if (incInScore > 20 && incInScore <= 50)
{
return 0.50f;
}
else if (incInScore > 50 && incInScore <= 100)
{
return 0.75f;
}
else if (incInScore > 100 && incInScore <= 200)
{
return 1f;
}
else
{
return 2f;
}
}
}

How can i wait until the rotation speed of a object is getting to some value then to slow down?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpinObject : MonoBehaviour
{
public float rotationMultiplier;
public GameObject[] objectsToRotate;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
for (int i = 0; i < objectsToRotate.Length; i++)
{
rotationMultiplier += 0.1f;
objectsToRotate[i].transform.Rotate(Vector3.forward, Time.deltaTime * rotationMultiplier);
}
}
}
With this line i speed up the rotation slowly:
rotationMultiplier += 0.1f;
Now i want to add a IF condition so if rotationMultiplier get to for example speed 500 then start slow down like:
rotationMultiplier -= 0.1f;
The problem is that rotationMultiplier is a float so i can't just check IF rotationMultiplier == 500
Add a boolean to check whether you must accelerate or decelerate
private bool slowDown = false;
for (int i = 0; i < objectsToRotate.Length; i++)
{
if( rotationMultiplier > 500)
slowDown = true ;
else if( rotationMultiplier < 0 )
slowDown = false;
rotationMultiplier = (slowDown) ? rotationMultiplier - 0.1f : rotationMultiplier + 0.1f;
objectsToRotate[i].transform.Rotate(Vector3.forward, Time.deltaTime * rotationMultiplier);
}
Otherwise, you could use Mathf.PingPong maybe :
for (int i = 0; i < objectsToRotate.Length; i++)
{
rotationMultiplier = Mathf.PingPong( Time.time, 500 ) ;
objectsToRotate[i].transform.Rotate(Vector3.forward, Time.deltaTime * rotationMultiplier);
}
You can use a bool to determine your state (Speed up or slow down)
public bool isIncreasing;
if(rotationMultiplier >= 500)
{
isIncreasing=false;
}
if(rotationMultiplier <= 0) //or your desired value
{
isIncreasing=true;
}
if(isIncreasing)
{
//do your speed up here
}
else
{
//do your slow down here
}
You can convert float to int then can check
for (int i = 0; i < objectsToRotate.Length; i++)
{
if(rotationMultiplier >= 500)
{
rotationMultiplier -= 0.1f;
}
else
{
rotationMultiplier += 0.1f;
}
objectsToRotate[i].transform.Rotate(Vector3.forward, Time.deltaTime * rotationMultiplier);
}

Unity - OnTriggerEnter bullet ricochet

i have some problems with simple ballistics.As i am new to coding and i wasted 2 days with searching, i decided to ask a question. I have a problem with my bullet.cs script, code works fine, except ricochet part. I used OnTriggerEnter beacuse bullets will penetrate different materials, but will bounce under specific angles, so i used collider as a trigger only. I know it can be dobe using OnCollisionEnter to determine normal and use Vector3.Reflect. But if collider is not set as a trigger only, bullets will be bouncing off from everithing a will never penetrate a wall. Just need a help with ricochet part on the bottom.
public Rigidbody rb;
private float vel;
private float kEnergy;
private bool AP = false;
private bool HP = false;
private bool ricochet = false;
// Use this for initialization
void Start () {
vel = 738f;
kEnergy = 2108f;
//HP == false;
Destroy (gameObject, 10);
rb = GetComponent<Rigidbody> ();
rb.velocity = transform.forward * vel;
Quaternion bulletRotaion = transform.rotation;
Debug.Log (bulletRotaion.eulerAngles);
}
// Update is called once per frame
void Update () {
float curVelocity = rb.velocity.magnitude;
if (curVelocity <= 0)
{
curVelocity = 0f;
}
}
void OnTriggerEnter (Collider c)
{
if (c.tag == "Wall") {
Quaternion localOffset = transform.rotation;
float impactAngleX = c.gameObject.GetComponent <MaterialDensity> ().angleX;
float impactAngleY = c.gameObject.GetComponent <MaterialDensity> ().angleY;
float impactAngleZ = c.gameObject.GetComponent <MaterialDensity> ().angleZ;
float angleX = localOffset.eulerAngles.x;
float angleY = localOffset.eulerAngles.y;
float angleZ = localOffset.eulerAngles.z;
float density = c.gameObject.GetComponent <MaterialDensity> ().materialDensity;
float ricochetX = (angleX + impactAngleX);
if (ricochetX > 360)
{
ricochetX = (ricochetX - 360);
}
if (ricochetX < 0)
{
ricochetX = (ricochetX + 360);
}
float ricochetY = (angleY + impactAngleY);
if (ricochetY > 360)
{
ricochetY = (ricochetY - 360);
}
if (ricochetY < 0)
{
ricochetY = (ricochetY + 360);
}
float ricochetZ = (angleZ + impactAngleZ);
if (ricochetZ > 360)
{
ricochetZ = (ricochetZ - 360);
}
if (ricochetZ < 0)
{
ricochetZ = (ricochetZ + 360);
}
if ((ricochetX > 60 && ricochetX < 300) || (ricochetY > 60 && ricochetY < 300) || (ricochetZ > 60 && ricochetZ < 300)) {
ricochet = true;
//Debug.Log (ricochet);
}
if ((ricochetX < 60 && ricochetX > 300) || (ricochetY < 60 && ricochetY > 300) || (ricochetZ < 60 && ricochetZ > 300)) {
ricochet = false;
//Debug.Log (ricochet);
}
Debug.Log (ricochet);
Debug.Log (ricochetX);
Debug.Log (ricochetY);
Debug.Log (ricochetZ);
if (AP)
{
density *= 0.9f;
}
if (HP)
{
density *= 3f;
}
//float vel = gameObject.GetComponent<GunNew>().velocity;
float curVelocity = rb.velocity.magnitude;
float velocityMod = curVelocity / vel;
float densityMod = density / velocityMod;
float curEnergy = (kEnergy * velocityMod);
float energyMod = (curEnergy * velocityMod);
rb = GetComponent<Rigidbody> ();
//Quaternion localOffset = transform.rotation;
float randomX = Random.Range (0.03f, 0f);
float randomY = Random.Range (0.03f, -0.03f);
if (randomX == 0)
{
randomX = 0.01f;
}
if (randomY == 0)
{
randomY = 0.01f;
}
localOffset.x += randomX;
localOffset.y += randomY;
if (curVelocity > densityMod && !ricochet) {
rb.rotation = localOffset;
rb.velocity = transform.forward * ((curVelocity - (curVelocity * (randomX + randomY))) - densityMod);
//Debug.Log (curVelocity);
//Debug.Log (energyMod);
}
if (curVelocity > densityMod && ricochet)
{
Vector3 objAngle = new Vector3 (impactAngleX, impactAngleY, impactAngleZ);
Vector3 bulletAngle = rb.rotation.eulerAngles;
Debug.Log (objAngle);
}
if (curVelocity <= densityMod)
{
//Debug.Log (curVelocity);
//Debug.Log (energyMod);
Destroy (gameObject);
}
}
}
second code is a code from wall.
public float materialDensity = 100f;
public float angleX;
public float angleY;
public float angleZ;
//Quaternion localOffset = transform.rotation;
// Use this for initialization
public void Start ()
{
GetComponent<Rigidbody> ();
Quaternion localOffset = transform.rotation;
float angleX = localOffset.eulerAngles.x;
float angleY = localOffset.eulerAngles.y;
float angleZ = localOffset.eulerAngles.z;
//Debug.Log (localOffset.eulerAngles.x);
}
// Update is called once per frame
void Update () {
}
Firstly, I would make a layers in your game for things that will ricochet, and things that don't.
Then when you test for collisions with your bullet you can only check for collisions with the ricochet layer. This will increase performance and also make coding much simpler.
From there you could rely on unity's physics to do it's own ricochet, or if you wanted to calculate it yourself you could do a raycast and use the raycast's normal as described above.
if(Physics.Raycast (shootRay, out shootHit, range, ricochetMask)) {
...

Categories