using UnityEngine;
using UnityEngine.Networking;
public class Interactable : NetworkBehaviour {
public float radius = 2f;
bool isFocus = false;
Transform player;
bool hasInteracted = false;
public Transform interactionPoint;
public virtual void Interact()
{
// This method is meant to be overwritten
Debug.Log("Interacting with " + transform.name);
}
private void Update()
{
if (isFocus && !hasInteracted)
{
float distance = Vector3.Distance(player.position, interactionPoint.position);
if(distance <= radius)
{
Interact();
hasInteracted = true;
}
}
}
public void onFocused(Transform Player)
{
isFocus = true;
player = Player;
}
public void onDeFocused()
{
isFocus = false;
player = null;
hasInteracted = false;
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, radius);
}
}
This is for the interaction which is overwritten.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class SphereBehaviour : Interactable {
public float countdown = 1;
public float timeLeft = 5f;
public override void Interact()
{
Debug.Log("Interacting with the Sphere object");
StartCoroutine(StartCountdown());
}
public IEnumerator StartCountdown() // Countdown from 5
{
countdown = timeLeft;
while (countdown > 0)
{
yield return new WaitForSeconds(1.0f);
countdown--;
}
}
The Problem is that this isn't networked and I can't think of the logic to do it. An Interface won't work or anything. Is there any possible solution which doesn't require changing everything?
I'm just trying to turn Brackeys set of youtube tutorials to something multiplayer.
I'm assuming you're using the public "countdown" variable for some UI element.
If you want each player to see their own countdown when they themselves touch this Sphere, this should work fine.
If anyone touching the sphere should trigger a countdown for everyone, then this will have to be done differently. You'll want the host/server to track interactions between players and spheres, then trigger the countdown coroutine in the clients.
I personally don't recommend #1 in any case, as collisions/interactions should be done server-side.
Related
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletParticle : MonoBehaviour
{
public float damage = 10f;
public ParticleSystem particleSystem;
public GameObject spark;
List<ParticleCollisionEvent> colEvents = new List<ParticleCollisionEvent>();
private void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
particleSystem.Play();
}
}
private void OnParticleCollision(GameObject other)
{
int events = particleSystem.GetCollisionEvents(other, colEvents);
for (int i = 0; i < events; i++)
{
Instantiate(spark, colEvents[i].intersection, Quaternion.LookRotation(colEvents[i].normal));
}
if (other.TryGetComponent(out enemy en))
{
en.TakeDamage(damage);
}
}
}
Does anyone know how to make the bullet have a cooldown please tell me?
A guy said to do something with the input so when the bullet shoots it has a cooldown.
`
that's a simple method using a timer it should be something like
using UnityEngine;
using System.Collections;
public class SimpleTimer: MonoBehaviour {
// i assigned the timer at 3 seconds
public float cooldownBullet = 3.0f;
public bool canShoot=false;
Update(){
targetTime -= Time.deltaTime;
if (Input.GetKeyDown(KeyCode.Mouse0) && canShoot==true)
{
canShoot=false;
particleSystem.Play();
}
if (targetTime <= 0.0f)
{
canShoot=true;
}
}
void timerEnded()
{
//do your stuff here.
}
}
Hope it works!
In the other answer, you can shoot only once, and then you have to wait. I would create it in a way that you can shoot multiple times and then it overheats. You might need to modify this code and play with the numbers to make it work as you want but that is the idea.
using UnityEngine;
using System.Collections;
public class CoolDownTimer: MonoBehaviour {
public float heat=0.0f;
public bool canShoot=true;
public float heatLimit=10.0f;
Update(){
if(heat > 0f)
heat -= Time.deltaTime;
if(heat < heatLimit)
canShoot = true;
if (Input.GetKeyDown(KeyCode.Mouse0) && canShoot==true)
{
particleSystem.Play();
heat++;
if(heat >= heatLimit){
canShoot=false
}
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShootBullets : MonoBehaviour
{
public float bulletDistance;
public bool automaticFire = false;
public float fireRate;
public Rigidbody bullet;
private float gunheat;
private bool shoot = false;
private GameObject bulletsParent;
private GameObject[] startpos;
// Start is called before the first frame update
void Start()
{
bulletsParent = GameObject.Find("Bullets");
startpos = GameObject.FindGameObjectsWithTag("Fire Point");
}
private void Fire()
{
for (int i = 0; i < startpos.Length; i++)
{
Rigidbody bulletClone = (Rigidbody)Instantiate(bullet, startpos[i].transform.position, startpos[i].transform.rotation, bulletsParent.transform);
bulletClone.velocity = transform.forward * bulletDistance;
Destroy(bulletClone.gameObject, 0.5f);
}
}
// Update is called once per frame
void FixedUpdate()
{
if (automaticFire == false)
{
if (Input.GetMouseButtonDown(0))
{
Fire();
}
}
else
{
if (shoot == true)
{
Fire();
shoot = false;
}
}
if (gunheat > 0) gunheat -= Time.deltaTime;
if (gunheat <= 0)
{
shoot = true;
gunheat = fireRate;
}
}
}
now the bullets firing up the air and i want the bullets to fire to a target with physics.
the main goal later is to make some kind of side mission where the player third person view should shoot on object and if and when hitting the object the object will fall down and then the player will be able to pick it up.
i am trying to Make The Mandelbrot set, i have the function thing working, zn = zn^
and i want to Visualizing the Mandelbrot set using circles, i tried this code but it cruses every time i compile, here's the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PaintMand : MonoBehaviour
{
[SerializeField] private GameObject CirclePaint;
[SerializeField] private RectTransform RedCircle;
[SerializeField] private Canvas canvas;
private float sumDistance = 0;
private bool HasFinshed = false;
private Vector2 start = new Vector2(2.133f,0.976f);
private void Update()
{
if (!HasFinshed)
{
sumDistance = AutoAxis.GetSumDistance();
MoveRed();
LoadRed();
}
}
public void MoveRed()
{
if(start.y < -0.988f)
{
HasFinshed = true;
}
else if(start.x <= -2.107f)
{
start.x = 2.133f;
start.y -= 0.20f;
}
else
{
start.x -= 0.20f;
}
RedCircle.anchoredPosition = start;
}
public void LoadRed()
{
if (IsUnstable())
{
GameObject NewCircle = Instantiate(CirclePaint, Vector3.zero,Quaternion.identity);
NewCircle.GetComponent<Image>().color = new Color(sumDistance,sumDistance,sumDistance);
NewCircle.transform.SetParent(canvas.transform);
NewCircle.GetComponent<RectTransform>().anchoredPosition = RedCircle.anchoredPosition;
}
}
private bool IsUnstable()
{
if(sumDistance > 1000)
{
return true;
}
return false;
}
}
the red circle is the c in the equation, zn = zn^ + c
and it moves every frame and checks if its unstable(the autoaxis is the class that makes the Visualizing the function) it gets the sum of the distance between all the circles and sends the float to the paintmad class, this cruses every time, pls help :(
What I'm trying to do is have my player stop moving so I can play animation through a trigger-event or just a custscene.
What I expect was for one of them to trigger the timer then play animation>player move.. like a cut-scene
Also there are no errors In any of them They just didn't stop player from moving or just stop the player when starting the game(or when I press play it just set forwardMovement to 0)
Here's the code I use:
public class Player_controls : MonoBehaviour
{
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
public int forwardMovement = 1000;
public void Update()
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
}
Things that I tried:
public void ForwardMovement()
{
forwardMovement = 0;
Invoke("Action", 2f);
}
public void Action ()
{
forwardMovement = 1000 ;
}
Which only works for ForwardMovement(); method nothing else
I tried these two things also:
Public static class MonoExtensions
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public float Delayer = 10f;
public static class MonoExtensions
{
public static void Timed_delay(this MonoBehaviour mono,Action function, float Delayer)
{
mono.StartCoroutine(Timed_delayRoutine(function,Delayer));
}
static IEnumerator Timed_delayRoutine(Action function, float Delayer)
{
yield return new WaitForSeconds(Delayer);
function();
}
public class `Player_Controls`: MonoBehaviour
{
public void PM ()
{
forwardMovement = 0;
}
void OnTriggerEnter(Collider other)
{
if (CompareTag("Power_up"))
{
this.Timed_delay(PM, Delayer);
}
}
}
Which just stop the player from moving an nothing else.
What I also tried was:
public class Player_Controls : MonoBehaviour
{
void Start()
{
StartCoroutine(ForwardMovement());
}
IEnumerator ForwardMovement()
{
forwardMovement = 0;
yield return new waitforseconds(Delayer);
forwardMovement = 1050;
}
void OnTriggerEnter(collider other)
{
if (CompareTag("Power_up"))
{
ForwardMovement();
}
}
}
Which did not work as in(it works but the timer part does nothing, so the player can't move when started the game )
Different way I tried
public class Player_Controls : MonoBehaviour
{
OnTriggerEnter(collider other)
{
Startcroutine(ForwardMovement ));
}
}
it didn't work but no Errors.
I tried this one by jazzhar:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
// Drag the player in the inspector here;
public Rigidbody rb;
// Youre speed variable for movement.
public float Speed = 5;
// Youre speed variable for movement.
public int forwardMovement = 1000;
// Set this "stopmoving" bool to true to prevent movement.
public bool stopMoving = false;
// Create and select the right layer in the inspector.
public LayerMask WichObjectStopsMovement;
public void Update()
{
// if stopMoving = true than Dont Add force.
if (stopMoving == false)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
private void OnCollisionEnter(Collision collision)
{
// if you're player touches a object and that object's layer
// is the same as "WichObjectStopsMovement" than disable Movement.
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = false;
}
}
}
It sorta works in a way if you set if
if (stopMoving == true)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
and
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = true;
}
then the player would be able to move but it will not trigger if hit the cube
it didn't work either but no Errors.
And some other timers I did but forgotten....
_________________________________________________________________March/6/21
public float Delayer = 10.0f;
I think found solution by doing this
private void OnTriggerEnter(Collider other)
{
if (CompareTag("Power_up"))
{
Delayer -= Time.deltaTime; <- this part giving me the error
if (Delayer => 0)
{
forwardMovement = 0;
}
}
}
but their one problem it giving me the this error Cannot convert lambda expression to type 'bool' because it is not a delegate type [Assembly-CSharp]csharp(CS1660) I don't know much about this even searching about doesn't help either
__________________________________________________________________March 28/21
this script is under player controls
this one works I made sure by doing Debug.Log("test");
void OnTriggerExit(Collider collision)
{
if (collision.gameObject.CompareTag("Power_up"))
{
forwardMovement = 0;
}
if (forwardMovement <= 0)
{
Debug.Log("test");
}
This might be a solution to you're problem, Fire-Source!:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
// Drag the player in the inspector here;
public Rigidbody rb;
// Youre speed variable for movement.
public float Speed = 5;
// Youre speed variable for movement.
public int forwardMovement = 1000;
// Set this "stopmoving" bool to true to prevent movement.
public bool stopMoving = false;
// Create and select the right layer in the inspector.
public LayerMask WichObjectStopsMovement;
public void Update()
{
// if stopMoving = true than Dont Add force.
if (stopMoving == false)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
private void OnCollisionEnter(Collision collision)
{
// if youre player touches a object and that object's layer
// is the same as "WichObjectStopsMovement" than disable Movement.
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = false;
}
}
}
This code uses a LayerMask, to create 1 click on any object and in the inspector go:
Click on Layer:
Add Layer:
Write in User Layer 6, StopMovement (or anything else).
Than in the object that should stop player movement:
Click on layer:
Than select the Layer that says StopMovement.
And in you're player's script drag the object into the rb variable.
and in "WichObjectStopsMovement" assign the StopMovement layer.
This should take care of everything is that ok?
So I put the object in the scene and then I made it "invisible" (deactivate if you will) from the inspector (the checkmark box next to the object's name) and after waiting 8 seconds it doesn't become visible. I am using Unity 2d and C#.
I have the game start paused for three seconds then plays after that which works. The first script is that one. The item is supposed to reappear after 8 seconds so after the game resumes, which doesn't work.
//delay before level starts script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class countDown : MonoBehaviour
{
public GameObject CountDown;
private void Start()
{
StartCoroutine("StartDelay");
}
void Update()
{
}
IEnumerator StartDelay()
{
Time.timeScale = 0;
float pauseTime = Time.realtimeSinceStartup + 3f;
while (Time.realtimeSinceStartup < pauseTime)
yield return 0;
CountDown.gameObject.SetActive(false);
Time.timeScale = 1;
}
{
//script for the flower to appear
IEnumerator Start()
{
print(Time.time);
yield return new WaitForSeconds(8);
print(Time.time);
flowerInScene.gameObject.SetActive(true);
}
[SerializeField] Transform flowerInScene;
}
I still don't really get your two methods called Start
You can simply call a StartCoroutine at the end of another Coroutine so you can chain them together (though there are surely better ways to do what you want in general):
using System.Collections;
using UnityEngine;
public class CountDown : MonoBehaviour
{
public GameObject CountDownObject;
public GameObject flowerObject;
private void Start()
{
StartCoroutine(Delay());
}
private IEnumerator Delay()
{
yield return new WaitForSeconds(3);
HideCountdown();
StartCoroutine(FlowerDelay());
}
private void HideCountdown()
{
CountDownObject.SetActive(false);
}
private IEnumerator FlowerDelay()
{
yield return new WaitForSeconds(8);
ShowFlower();
}
private void ShowFlower()
{
flowerObject.SetActive(true);
}
}
I personaly don't like Coroutines .. they are not so easy to debug sometimes. I would prefer doing something like this with simple timers (though in the first moment it does look worse). Advantage is I can now directly watch the timer count down in the inspector:
using UnityEngine;
public class SimpleCountDown : MonoBehaviour
{
[Header("The Objects")]
public GameObject CountDownObject;
public GameObject FlowerObject;
[Header("Settings")]
// Here you can adjust the delay times
public float StartOffset = 3;
public float FlowerOffset = 8;
[Header("Debug")]
public float startTimer;
public float flowerTimer;
public bool isStartDelay;
public bool isFlowerDelay;
private void Start()
{
startTimer = StartOffset;
flowerTimer = FlowerOffset;
isStartDelay = true;
}
private void Update()
{
if (!isStartDelay && !isFlowerDelay) return;
if (isStartDelay)
{
startTimer -= Time.deltaTime;
if (startTimer <= 0)
{
HideCountdown();
isStartDelay = false;
isFlowerDelay = true;
}
}
if (isFlowerDelay)
{
flowerTimer -= Time.deltaTime;
if (flowerTimer <= 0)
{
ShowFlower();
isFlowerDelay = false;
this.enabled = false;
}
}
}
private void HideCountdown()
{
CountDownObject.SetActive(false);
}
private void ShowFlower()
{
FlowerObject.SetActive(true);
}
}