Starting a Particle System in Unity with Buttons - c#

Hello everyone I made a rocket fire partical with Unity's partical system but Idk how can I make it activated when I press my thrust engine button (W and up Arrow is my buttons)
This is my code;
public class Rocket : MonoBehaviour
{
private Rigidbody2D rb;
public float amount;
public float MaxVelocity = 3;
public float RotationSpeed = 3;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
public void ThrustForward(float amount)
{
Vector2 force = transform.up * amount;
rb.AddForce(force);
}
// Update is called once per frame
void Update()
{
float Yaxis = Input.GetAxis("Vertical");
float Xaxis = Input.GetAxis("Horizontal");
ThrustForward(Yaxis);
Rotate(transform, Xaxis * RotationSpeed);
}
private void ClampVelocity()
{
float x = Mathf.Clamp(rb.velocity.x, -MaxVelocity, MaxVelocity);
float y = Mathf.Clamp(rb.velocity.y, -MaxVelocity, MaxVelocity);
rb.velocity = new Vector2(x, y);
}
private void Rotate(Transform t,float amount)
{
t.Rotate(0, 0, amount);
}
}
Please help me how can I start a particle system in unity with buttons
Thanks!!

If You Have A Particle System, You Can Make A Variable In Your Code Like, Following:
public ParticleSystem particle;
You Can Play The Particle System By Using The Variable With .Play() in end, for example, if you have created a variable like above as I suggested, you can play the particle system whenever you want.
The Way We Do It Is Pretty Simple.
particle.Play();
Direct Solution
Remove Everything From Your Script And Try Overwriting It With Following Code
public class Rocket : MonoBehaviour
{
private Rigidbody2D rb;
public ParticleSystem particle;
public float amount;
public float MaxVelocity = 3;
public float RotationSpeed = 3;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
public void ThrustForward(float amount)
{
Vector2 force = transform.up * amount;
rb.AddForce(force);
particle.Play();
}
// Update is called once per frame
void Update()
{
float Yaxis = Input.GetAxis("Vertical");
float Xaxis = Input.GetAxis("Horizontal");
ThrustForward(Yaxis);
Rotate(transform, Xaxis * RotationSpeed);
// You Can Do Exactly Same Thing For Arrow Key
// To Get Better Rusults Try Messing With The Particle System's Settings
}
private void ClampVelocity()
{
float x = Mathf.Clamp(rb.velocity.x, -MaxVelocity, MaxVelocity);
float y = Mathf.Clamp(rb.velocity.y, -MaxVelocity, MaxVelocity);
rb.velocity = new Vector2(x, y);
}
private void Rotate(Transform t,float amount)
{
t.Rotate(0, 0, amount);
}
}

Related

My 3D racing game has some problems like wheels turning y axis and car not going anywhere

My car's tires spin but the car doesn't move an inch and the wheels turn into y axis instead of left and right. Here is my code, i added rigidbody and boxcollider onto my car aswell maybe that's a problem causing the car not to move? (i made sure to put the collider above the wheels to make sure that they spin.)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarController : MonoBehaviour
{
private float horizontalInput;
private float verticalInput;
private float steerAngle;
private bool isBreaking;
public WheelCollider FrontLeftCollider;
public WheelCollider FrontRightCollider;
public WheelCollider BackLeftCollider;
public WheelCollider BackRightCollider;
public Transform FrontLeftTransform;
public Transform FrontRightTransform;
public Transform BackLeftTransform;
public Transform BackRightTransform;
public float maxSteeringAngle = 30f;
public float motorForce = 50f;
public float brakeForce = 0f;
private void FixedUpdate()
{
GetInput();
HandleMotor();
HandleSteering();
UpdateWheels();
}
private void GetInput()
{
horizontalInput = Input.GetAxis("Horizontal");
verticalInput = Input.GetAxis("Vertical");
isBreaking = Input.GetKey(KeyCode.Space);
}
private void HandleSteering()
{
steerAngle = maxSteeringAngle * horizontalInput;
FrontLeftCollider.steerAngle = steerAngle;
FrontRightCollider.steerAngle = steerAngle;
}
private void HandleMotor()
{
FrontLeftCollider.motorTorque = verticalInput * motorForce;
FrontRightCollider.motorTorque = verticalInput * motorForce;
brakeForce = isBreaking ? 3000f : 0f;
FrontLeftCollider.brakeTorque = brakeForce;
FrontRightCollider.brakeTorque = brakeForce;
BackLeftCollider.brakeTorque = brakeForce;
BackRightCollider.brakeTorque = brakeForce;
}
private void UpdateWheels()
{
UpdateWheelPos(FrontLeftCollider, FrontLeftTransform);
UpdateWheelPos(FrontRightCollider, FrontRightTransform);
UpdateWheelPos(BackLeftCollider, BackLeftTransform);
UpdateWheelPos(BackRightCollider, BackRightTransform);
}
private void UpdateWheelPos(WheelCollider wheelCollider, Transform trans)
{
Vector3 pos;
Quaternion rot;
wheelCollider.GetWorldPose(out pos, out rot);
trans.rotation = rot;
trans.position = pos;
}
}
If needed i can send screenshots of things please don't be shy to ask.
I haven't tried anything too afraid to make it worse
A rigidbody will not move until some kind of force is applied to it, or you use it's MovePosition method. Here is a link ... https://docs.unity3d.com/ScriptReference/Rigidbody.MovePosition.html

Instantiated object doesn't follow iTween path, how do I fix this?

So essentially I've:
Instantiated a new prefab of an object
Set all the variables in the transform of the prefab
Copied the script for the initial capsule (which works) into the prefab spawning script
And yet my prefabs for some reason really do not want to follow the path around, how do I make them follow the path?
public class PathFollower : MonoBehaviour
{
public float movementSpeed;
//private float pathProgress = 0;
public GameObject objectToSpawn;
public Transform[] positionPoint;
[Range(0,1)]
public float value;
void Start()
{
Debug.Log(iTween.PathLength(positionPoint));
}
void Update()
{
movementSpeed = 10f;
if (value < 1)
{
value += Time.deltaTime / movementSpeed;
}
iTween.PutOnPath(objectToSpawn, positionPoint, value);
}
private void OnDrawGizmos()
{
iTween.DrawPath(positionPoint,Color.green);
}
}
public class deployCapsule : MonoBehaviour
{
public float movementSpeed;
public Transform[] positionPoint;
public GameObject CapsulePrefab;
[Range(0, 1)]
public float value;
//movementspeed = 10f;
// Start is called before the first frame update
void Start()
{
}
void Update()
{
GameObject a = Instantiate(CapsulePrefab) as GameObject;
a.transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width - 20, Screen.height - 20, 10));
//if (Input.GetKeyDown(KeyCode.Space))
//{
a.GetComponent<PathFollower>().positionPoint = positionPoint;
//}
movementSpeed = 10f;
if (value < 1)
{
value += Time.deltaTime / movementSpeed;
}
iTween.PutOnPath(a, positionPoint, value);
}
}
Where the scripts are attached, also shows transform arrays:
Hard to say what is the exact problem, but from the image no 3 I see that value of variable value is 1 which may cause the problem.
It should be 0 so the object is at the beginning of the path.
You can use Start method to explicitly set the value of the value variable
Despite this, I wouldn't recommend you to instantiate game objects every frame (in Update method) because it's not efficient and probably will never have such use case.

How to make FPS crawl?

I'm using Unity New Input System for my FPS game and I have figured out the movement and the mouselook. However, I'm trying to add a crawling feature to my moving script. I don't want the player to be holding down a button for crawling, it would be better to click a button to change the status from walking to crawling and then just move accordingly. and of course, the mouselook will differ in every state. How would I achieve that with the minimal code changes?
Movement class:
public class Movement : MonoBehaviour
{
[SerializeField] CharacterController controller;
[SerializeField] float walkSpeed = 10f;
[SerializeField] float runSpeed = 35f;
float moveSpeed;
Vector2 horizontalInput;
[SerializeField] float jumpHeight = 3.5f;
bool jump, running;
[SerializeField] float gravity = -30f; //-9.81
Vector3 verticalVelocity = Vector3.zero;
[SerializeField] LayerMask groundMask;
bool isGrounded;
Vector3 horizontalVelocity;
private void Update()
{
isGrounded = Physics.CheckSphere(transform.position, 0.1f, groundMask);
if (isGrounded)
{
verticalVelocity.y = 0;
}
// Jump: v = sqrt(-2 * jumpheight* gravity)
if (jump)
{
if (isGrounded)
{
verticalVelocity.y = Mathf.Sqrt(-2f * jumpHeight * gravity);
}
jump = false;
}
verticalVelocity.y += gravity * Time.deltaTime;
controller.Move(verticalVelocity * Time.deltaTime);
if (running)
{
moveSpeed = runSpeed;
horizontalVelocity = (transform.right * horizontalInput.x + transform.forward * horizontalInput.y) * moveSpeed;
controller.Move(horizontalVelocity * Time.deltaTime);
}
else
{
moveSpeed = walkSpeed;
horizontalVelocity = (transform.right * horizontalInput.x + transform.forward * horizontalInput.y) * moveSpeed;
controller.Move(horizontalVelocity * Time.deltaTime);
}
}
public void ReceiveInput(Vector2 _horizontalInput)
{
horizontalInput = _horizontalInput;
}
public void OnJumpPressed()
{
jump = true;
}
public void OnRunningPressed() {
running = true;
}
}
MouseLook class:
public class MouseLook : MonoBehaviour
{
[SerializeField] float sensitivityX = 8f;
[SerializeField] float sensitivityY = 0.5f;
float mouseX, mouseY;
[SerializeField] Transform playerCamera;
[SerializeField] float xClamp = 75f;
float xRotataion = 0f;
private void Update()
{
transform.Rotate(Vector3.up, mouseX * Time.fixedDeltaTime);
xRotataion -= mouseY;
xRotataion = Mathf.Clamp(xRotataion, -xClamp, xClamp);
Vector3 targetRotation = transform.eulerAngles;
targetRotation.x = xRotataion;
playerCamera.eulerAngles = targetRotation;
}
public void ReceiveInput(Vector2 mouseInput)
{
mouseX = mouseInput.x * sensitivityX;
mouseY = mouseInput.y * sensitivityY;
}
}
InputManager class:
public class InputManager : MonoBehaviour
{
[SerializeField] Movement movement;
[SerializeField] PlayerInteractions playerInteractions;
[SerializeField] MouseLook mouseLook;
PlayerControls controls;
PlayerControls.GroundMovementActions groundMovement;
Vector2 horizontalInput;
Vector2 mouseInput;
private void Awake()
{
controls = new PlayerControls();
groundMovement = controls.GroundMovement;
// groundMovement.[action].performed += context => do something
groundMovement.HorizontalMovement.performed += ctx => horizontalInput = ctx.ReadValue<Vector2>();
groundMovement.Jump.performed += _ => movement.OnJumpPressed();
groundMovement.Running.performed += _ => movement.OnRunningPressed();
groundMovement.PickingUp.performed += _ => playerInteractions.OnPickingUp();
groundMovement.MouseX.performed += ctx => mouseInput.x = ctx.ReadValue<float>();
groundMovement.MouseY.performed += ctx => mouseInput.y = ctx.ReadValue<float>();
groundMovement.Open.performed += _ => playerInteractions.OnOpenPressed();
}
private void Update()
{
movement.ReceiveInput(horizontalInput);
mouseLook.ReceiveInput(mouseInput);
}
private void OnEnable()
{
controls.Enable();
}
private void OnDestroy()
{
controls.Disable();
}
}
I failed to find anything like this online and I don't know how to achieve it using the new input system but here is my attempt:
public class crawlScript : MonoBehaviour
{
CapsuleCollider playerCol;
float originalHeight;
public float reducedHeight;
bool crawl = false;
void Start()
{
playerCol= GetComponent<CapsuleCollider>();
originalHeight= playerCol.height;
}
// Update is called once per frame
void Update()
{
if (crawl)
{
OnCrouch();
}
else if (!crawl)
{
GoUp();
}
}
public void OnCrouch()
{
playerCol.height= reducedHeight;
}
void GoUp()
{
playerCol.height = originalHeight;
}
public void OnCrawl()
{
crawl= true;
}
And added this to the InputManager class:
groundMovement.Crawl.performed += _ => crawlscript.OnCrawl();
You will need to
Create a public boolean variable for whether the player is crawling or not, because this will almost certainly be needed in the future by this script or other scripts.
Create a crawling animation
Create two functions for enabling and disabling crawl, that will toggle the animation, change the players walk speed, and do other things that you may want to add (like toggle the visibility of any objects in the player's hands until they get back up).
The code should look something like this:
public String crawlkey = "left shift";
public bool iscrawling = false;
// put in Update()
if(!crawling){
if(Input.GetKeyDown(crawlkey)){
iscrawling = true;
handleCrawlStart();
}
} else if(Input.GetKeyDown(crawlkey)){
iscrawling = false;
handleCrawlEnd;
}

Trying to make my character respawn when variable playerlife goes lower than zero

I am trying to make it so my character is teleported to a respawn position when their life hits zero. Everything functions as intended besides the teleport mechanic. I have auto sync transforms enabled, but when my character reaches 0 (or less) it does not teleport my character. I have setup everything within the inspector as well, and have referenced my player object and my respawn point. Below is my code:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerLife : MonoBehaviour
{
public static float playerLife = 200f;
public float totaltime = 0f;
public Transform respawn;
public GameObject player;
Text life;
void Start()
{
life = GetComponent<Text>();
}
void Update()
{
life.text = "Health: " + playerLife;
if (playerLife <= 0)
{
playerLife = 200;
player.transform.position = respawn.transform.position;
}
}
void OnTriggerEnter(Collider collider)
{
if (collider.gameObject.CompareTag("healthpotion"))
playerLife += 50f;
if (collider.tag == "healthpotion")
Destroy(collider.gameObject);
}
void OnTriggerStay(Collider collider)
{
totaltime += Time.deltaTime;
if (collider.gameObject.CompareTag("lava"))
{
if (totaltime > 1)
{
playerLife -= 1f;
totaltime = 0f;
}
}
if (collider.gameObject.CompareTag("lavatwo"))
{
if (totaltime > 1)
{
playerLife -= 50f;
totaltime = 0f;
}
}
}
}
You haven't defined the position for respawn. So instead of:
public Transform respawn;
Just use:
public Vector3 respawn = new Vector3(x, y, z);
Then:
player.transform.position = respawn;

I'm not sure why but my add force isn't working i have a rigidbody2d, and the code looks correct but it still won't work?

I'm not sure why but my .addforce on my rigidbody isn't working.
I have tried following the official unity addforce tutorial.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArrowController : MonoBehaviour
{
public Rigidbody2D rb;
public float speed = 5.0f;
public Vector2 pos;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
faceMouse();
testForClick();
}
void faceMouse()
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 differance = GameObject.Find("gunArm").transform.position - mousePos;
float gunAngle = Mathf.Atan2(differance.y, differance.x) * Mathf.Rad2Deg;
GameObject.Find("gunArm").transform.rotation = Quaternion.Euler(0, 0, gunAngle);
}
void testForClick()
{
if (Input.GetMouseButtonDown(0))
{
print("click");
rb.AddForce(transform.forward);
}
}
}
I expect arrow to have force added to it in the forwards direction but it just prints out "click" (The message I added to ensure the mouse-click was working).
I'm not sure why but I created a test script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
public Rigidbody2D rb;
public float speed = 20.0f;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
print("click");
rb.AddForce(transform.right * speed, ForceMode2D.Impulse);
}
rotate();
}
private void rotate()
{
}
}
I also edited my old script to this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArrowController : MonoBehaviour
{
public Rigidbody2D rb;
public float speed = 50.0f;
public Vector2 pos;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
faceMouse();
testForClick();
}
void FixedUpdate()
{
if (doForce == true)
{
doForce = false;
rb.AddForce(transform.forward * speed, ForceMode2D.Impulse);
}
}
private bool doForce;
private GameObject gunArm;
private Camera cam;
private void faceMouse()
{
// try to reuse the reference
if (!cam) cam = Camera.main;
var mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
// try to re-use the reference
if (!gunArm) gunArm = GameObject.Find("gunArm");
var difference = rb.transform.position - mousePos;
var gunAngle = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
rb.transform.rotation = Quaternion.Euler(0, 0, gunAngle);
}
void testForClick()
{
if (Input.GetMouseButtonDown(0))
{
print("click");
// only set the flag
doForce = true;
}
}
void place()
{
}
}
and the test worked by itself with no rotation and on the main script only the rotation worked so i tried having both scripts active at the same time and it started working, thanks for all the help on this issue.
Despite the fact that isn't working is a quite weak description:
First of all you should do it in FixedUpdate but get the input in Update.
Second reduce the Find calls in Update .. very inefficient. It would be better to reference them via the Inspector if possible. Otherwise maybe in Start .. the way I show here is the last resort with lazy initialization assuming your script might be spawned later on runtime
Additionally (thanks to EricOverflow) you might want to rather pass ForceMode.Impulse to AddForce since you add the force only once and not continuesly.
public class ArrowController : MonoBehaviour
{
public Rigidbody2D rb;
public float speed = 5.0f;
public Vector2 pos;
// store and re-use references!
// would be better to already reference them via drag&drop
// in the Inspector
[SerializeField] private GameObject gunArm;
[SerializeField] private Camera cam;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
testForClick();
}
private void FixedUpdate()
{
// also do this here
faceMouse();
if (doForce)
{
doForce = false;
rb.AddForce(transform.forward, ForceMode.Impulse);
}
}
private bool doForce;
private void faceMouse()
{
// try to reuse the reference
if(!cam) cam = Camera.main;
var mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
// try to re-use the reference
if (!gunArm) gunArm = GameObject.Find("gunArm");
var difference = gunArm.transform.position - mousePos;
var gunAngle = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
gunArm.rotation = Quaternion.Euler(0, 0, gunAngle);
}
private void testForClick()
{
if (Input.GetMouseButtonDown(0))
{
print("click");
// only set the flag
doForce = true;
}
}
}
The reason your code doesn't do anything is not because it doesn't work, but instead because transform.forward is a vector with magnitude 1. Adding a force of magnitude 1 will not do much to most objects, and friction will likely slow down the object again.
Try adding a force with a higher strength and ForceMode.Impulse instead:
float strength = 50f;
rb.AddForce(transform.forward * strength, ForceMode.Impulse);
Update:
It looks like you want the gun to face your mouse position and that's where your problem might be:
Let's try using Quaternion.LookRotation to get that working instead of doing to math manually.
Maybe:
GameObject gunArm;
void Awake()
{
gunArm = GameObject.Find("gunArm");
}
void faceMouse()
{
Vector3 difference = mousePos - gunArm.transform.position;
difference.z = 0;
gunArm.transform.rotation = Quaternion.LookRotation(difference);
}

Categories

Resources