Set gameObject active Unity C# - c#

A game object has force applied to it in the positive direction, then after some time it has a force applied to it in the negative direction.
If the force is applied in the negative direction, this means game over and I want to display a totally different gameObject which is the game over gameObject called icetextureONfile. My method is not working I get error "type 'UnityEngine.GameObject' does not contain a definition for icetextureONfile". I am having a hard time refe
public void FixedUpdate() {
// No action happened yet
gameObject.icetextureONfile.SetActive (false);
// Increase the kick timer
kickTimer += Time.fixedDeltaTime;
// If the next kick time has came
if (nextKick < kickTimer) {
// Schedule the kick back corresponding to the current kick
nextKickBacks.Enqueue (nextKick + 100f);
// Apply the kick force
rb.AddForce (transform.up * thrust, ForceMode.Impulse);
// Plan the next kick
nextKick = kickTimer + Random.Range (MinKickTime, MaxKickTime);
}
// If there are more kick backs to go, and the time of the closest one has came
if (0 < nextKickBacks.Count) {
if (nextKickBacks.Peek () < kickTimer) {
// Apply the kick back force
rb.AddForce (-transform.up * thrust, ForceMode.Impulse);
// Game object was kicked down, set active game over object
gameObject.icetextureONfile.SetActive (true);
// Dequeue the used kick back time
nextKickBacks.Dequeue ();
}
}
}

If your wanting to deactivate one and then activate the other you could just add this to the class make sure its not inside the function
public GameObject iceTexture;
then drag and drop that object into the spot shown in the script in unity called iceTexture. Then just make sure you deactivate the object that the script is attached to and activate the iceTexture object.
gameObject.SetActive(false);
iceTexture.SetActive(true);
This page might help you.

This syntax worked for me
GameObject.Find ("icetextureONfile").SetActive(false);
As opposed to what is found in the Unity docs
gameObject.SetActive(false);
The first worked for me, the second did not. I am not a great programmer, so maybe it is just a matter of context.
Edit
It is commonly known that it is difficult to SetActive(true) after the object has already been SetActive(false). This is because the attached script becomes deactivated too. See Unity forums for details on why this is a nightmare.
To overcome this I have chosen a different route that accomplishes the same thing.
I set the size of the object to 0 until I needed it.
GameObject.Find ("icetextureONfile").transform.localScale = new Vector3(0, 0, 0);
GameObject.Find ("icetextureONfile").transform.localScale = new Vector3(0.02f, 0.02f, 0.02f);
Note that 0.02 is the size of my object in particular and may not be the exact same size as yours.

Related

My animations aren't playing when they should be

So Basically, I am creating a wandering ai character in unity using c# and the wandering is all working fine, but when the certain animations are supposed to play, they don't. I will include the code I am using to make this happen. I am also using an animator component on the model and the animations are all properly named and align with the animation in the animator's names and the animations are from mixamo. Any help is much appreciated because I am completely stuck!
void Update()
{
if (isWandering == false)
{
StartCoroutine(Wander());
}
if (isRotatingRight == true)
{
gameObject.GetComponent<Animator>().Play("idle");
transform.Rotate(transform.up * Time.deltaTime * rotSpeed);
}
if (isRotatingLeft == true)
{
gameObject.GetComponent<Animator>().Play("idle");
transform.Rotate(transform.up * Time.deltaTime * -rotSpeed);
}
if (isWalking == true)
{
gameObject.GetComponent<Animator>().Play("waalk");
transform.position += transform.forward * moveSpeed * Time.deltaTime;
}
}
Really consider using Animator parameters and transitions, it will save a lot of headache later on.
Anyways, regarding the question: Your code is in Update, which means it runs every frame.
That means every frame you're telling the Animator to play the state with that name, so every frame it starts the animation of that state over again. The result would be that your object would be stuck on the first frame of whatever animation.
Instead, you should call Play just once, when the desired conditions change.
Incidentally, that's one example of when it would be more convenient to use Animator parameters, since with transitions you are querying for specific conditions that take the animator from one state to the other, so you would get this "run just once" behaviour for free.
SORRY I FOUND THE ANSWER I WAS DOING EVERYTHING TO A MODEL THAT WASN'T RIGGED 😅 IT'S ALL GOOD NOW THANKS FOR THE HELP :)

I want to spawn my zombies in my game at a random location but I want to make sure to not spawn the inside the buildings

Currently in my script I am spawning in 125 zombies randomly all over my map however with my current code it just spawns them everywhere including inside the buildings. I want to keep the random spawns so i can't make exact spawn locations. Does anyone know how to block them from spawning inside buildings?
My current code for spawning them in (I am a noob so sorry if code is bad/messy)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ZombieRandomSpawn : MonoBehaviour
{
public GameObject ZK;
public int xPos;
public int zPos;
public int enemyCount;
// Start is called before the first frame update
void Start()
{
while (enemyCount < 125)
{
xPos = Random.Range(1, 165);
zPos = Random.Range(1, 215);
Instantiate(ZK, new Vector3(xPos, 0.3f, zPos), Quaternion.identity);
enemyCount = enemyCount + 1;
}
}
}
I would make an array of empty game objects that would be the possible spawn locations. Then place them anywhere you want, outside of the buildings. Then each time a zombie spawns, make it randomly select a spawn location from the array of locations that you made.
I would not use a SphereCast as suggested here!
As the name says it casts a sphere along a certain direction and checks if it hits anything on its way.
You probably rather would use an Physics.CheckSphere which checks for any colliders around a certain point within a certain radius without returning them since we are not interested in the hit Colliders anyway but only in the return value (bool).
In this specific use-case though it might not work as expected since in Start it might happen that not all physics related things are correctly initialized yet. I would wait until the first FixedUpdate call like e.g.
// Adjust this via the Inspector
[Tooltip("How far away from any collider do zombies have to spawn?")]
[SerializeField] private float zombySpawnDistanceThreashold = 0.3f;
// Yes, if you make Start return IEnumerator
// Unity automatically runs it as a Coroutine
private IEnumerator Start ()
{
// Wait for the first physics Update
yield return new WaitForFixedUpdate ();
// We don't actually care about the hits
// We only need to know IF we hit anything at all
// But this is way more efficient then everytime allocating a new array
var hits = new Collider[1];
while (enemyCount < 125)
{
// I assume you don't need to have exact INT values but can use any FLOAT value between them
// If that's the case make sure to use the FLOAT version here
var xPos = Random.Range(1f, 165f);
var zPos = Random.Range(1f, 215f);
var spawnPos = new Vector3(xPos, 0.3f, zPos);
// If we hit something we have to continue and pick a new random position
// Note: You might want/need to ignore the floor layer if your radius is too big since it would count as hit
if(Physics.OverlapSphereNonAlloc(spawnPos, zombySpawnDistanceThreashold, hits) > 0) continue;
Instantiate(ZK, spawnPos, Quaternion.identity);
// (Not sure if needed) Resimulate the physics to take the newly added zomby collider into account
Physics.Simulate(0.00001f);
enemyCount++;
}
}
As an alternative to skipping the spawn in case if a hit you could also use Physics.OverlapSphereNonAlloc and then use Physics.ComputePenetration in order to get a direction and distance of where and how far you have to move the zomby in order to push it out of the hit collider.
For an easy approach, I would consider looking into spherecast. Before spawning a zombie, cast a sphere and if it hits a building then try another spot to spawn. There is the potential for this to take a lot of computational time as it is randomly picking points and checking if it is valid. There is the case where it continually randomly picks points inside of buildings.
A more solid approach would be to predefined the bounds of where your buildings are, then only random pick places outside of these ranges. It also heavily depends on how large your building is or how many buildings you have. It is a rather vague question so more detail can help give a more exact answer.

Find and add the velocity of a Rigidbody that's directly below another? (Unity + C#)

I have an issue that I've not been able to solve for a few days now and without it working I can't move on with my project, so your help would be greatly appreciated!
What I'm trying to do is 'find' the velocity of an object that is directly below my 2D sprite (that also contains a Rigidbody and 2D box collider) and then add that velocity (in the same direction) to the object that is 'looking' for it.
I feel like ray-casting might be part of the answer but I'm not sure how to use that, especially in this context.
The idea behind this is I have a platform that can carry objects stacked on top of each other, so you move the mouse, it manipulates the platforms velocity, but this causes the objects on-top to fly backwards, no mater how high the friction is.
Here is the platform code:
void Update()
{
float distance_to_screen = Camera.main.WorldToScreenPoint(gameObject.transform.position).z;
Vector3 pos_move = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance_to_screen));
mouseDelta = pos_move - lastMousePosition;
acceleration = mouseDelta.x * 0.4f;
platformVelocity += acceleration;
platform.velocity = new Vector2(platformVelocity, 0) * speed;
lastMousePosition = pos_move;
}
Thank you for taking the time to read this, I would very much appreciate any help you can give!
Is it necessary to 'find' that object? 'Finding' may be difficult & costing.
Can you hold the 'below-thing' reference and pass it to 'above-thing'?
I'm assuming you have some method on objects that checks whether it's on a moving platform. One option is to add an IsOnMovingPlatform flag on those objects. Then use a similar method to check if any object is on top of the "IsOnMovingPlatform == true" objects. Keep doing passes on that method until you don't come up with any more flags set to true.
So, i'm trying to understand your question and I think I might know what you're talking about.
Are you saying that you want your game object (2d sprite) to stay on the platform as its moving? I have had the same problem, where a platform is moving and my player (game object) slides off- and this is how I fixed it.
Add a box collider to the platform (trigger). When the player enters the platform, make the player's transform the platform. That way, when the platform moves- the player moves with it no matter what the speed is.
For example:
void OnTriggerEnter2D(Collider2d collider){
if(collider.tag.equals("Player")){ // you only want the player to work
// attach script to platform for "this.transform" to work
collider.transform.SetParent(this.transform);
}
}
then, to unparent the transform "otherwise, even when the player is off the platform, it will move with the platform.
void OnTriggerExit(Collider2d collider){
// assuming your player isn't supposed to have a parent!
collider.transform.parent = null;
}
Sorry if I misunderstood your question! If this is what you were going for, finding the velocity of the platform is not necessary. Also, this is uncompiled code- if you have issues let me know.
EDIT:
To add a bit of a give, for the entire duration that the player is in contact with the platform, we can add a little bit of a negative force to shove the player a little bit!
We do this by using OnTriggerStay2D (assuming your game is 2d, otherwise use OnTriggerStay).
For example:
void OnTriggerStay2D(Collider2d collider){
if(collider.tag.equals("Player")){
collider.getComponent<Rigidbody2D>().addForce(new vector2(forceToAdd, 0));
}
}
now, that "forceToAdd" variable should be based on the speed and direction that your platform is going. Does your platform have a rigid body on it? if so you can get your force variable by retrieving the rigid body from the platform (getcomponent()) and get the X velocity from it. With this velocity, experiment with dividing it by numbers until you find a good fit, multiply it by -1 (because you want to push the player in the opposite direction of the platform travel), then this will be your forceToAdd!
However, if your platform is not using a Rigidbody, then a way you can do this is record the x positions in your script (just two positions, and subtract these to find the distance in an update method), multiply by -1, try dividing by a number (experiment with this) and that can be your force to add variable.
Also, my code for the OnTriggerStay2d is rough, the spelling could be a bit wrong- but this will give you a rough idea for a solution! ALSO.. I don't think getting the component of a rigid body should be done in every frame, a way around this would to have your rigid body component as a global variable in the script, then set your rigid body on OnTriggerEnter2d, this way it will only retrieve it once (instead of every frame) which I assume would be more efficient!
Good luck! and if you have any questions il try to help!
This is a raycast2d version, I tested it and it works much better than the trigger collider version :).
using UnityEngine;
using System.Collections;
public class RaycastFeetDeleteLater : MonoBehaviour {
[SerializeField] private float raycastDist = 0.1f;
[SerializeField] Transform feet;
[SerializeField] private float xForceDampener = 0.1f;
private Rigidbody2D rb2d;
// Use this for initialization
void Start () {
rb2d = GetComponent<Rigidbody2D> ();
}
// Update is called once per frame
void FixedUpdate () {
RaycastDown ();
}
private void RaycastDown(){
RaycastHit2D hit = Physics2D.Raycast (feet.position, Vector2.down, raycastDist);
if (hit.collider != null) {
print (hit.transform.tag);
if (hit.collider.tag.Equals ("Platform")) {
transform.SetParent (hit.transform);
Vector2 force = new Vector2 ((hit.transform.gameObject.GetComponent<Rigidbody2D> ().velocity.x * xForceDampener) * -1, 0);
print (force);
rb2d.AddForce (force);
} else if (transform.parent != null) {
print ("UNPARENT");
transform.parent = null;
}
} else {
if (transform.parent != null) {
transform.parent = null;
}
}
Debug.DrawRay (feet.position, Vector3.down, Color.green, raycastDist);
}
}
This script is attached to the player! No need to have scripts on the platforms, which was the main reason my previous method was a pain :P
Basically this script does the following:
- Gets rigidbody2d of the player on start (we will be adding forces to the player with it soon, so might as well store it in a variable!
On FixedUpdate (Different than Update, FixedUpdate is called on Physics update, where as Update is called every frame) I have read that raycast should use FixedUpdate, I suppose because it is a Physics method!
RaycastDown shoots a 2D raycast directly down from the feet position (to get the feet, create a child object of the player, put the position of the feet a tiny bit below the player, NOT ON THE PLAYER- I will explain why in a second why that will mess up everything! Then drag the feet GameObject on to the "feet" slot of the script.)
Raycast shoots from feet directly down at a distance that is changeable in the editor (raycastDist) I found a distance of 0.1f was perfect for my needs, but play around with it for yours! You can actually see a drawing of your Ray by using Debug.DrawRay as seen in the code, the ray is only visible in the editor- not game view! But this will help, especially with positioning the feet.
Checks if it hit an object with a collider, if so check if the objects tag is a Platform (set the platforms to a new tag and call it Platform).
If it hits a platform set the parent of the player to the platform (like the last script) and start applying a little force to the player in the negative direction that the platform is traveling (we get the rigid body of the platform to find its velocity).
If the raycast does not hit a platform, unparent it so the player can move freely.
Thats basically it, however...
Please note:
This script needs to be on the player, not any of the players child objects, since this script will unparent the player from any platforms- if you have the script on a child object of the player it will unparent from the player- which is horrible. So The script MUST be on the root game object of the player. There are ways around this if for some reason you can't.
As mentioned before, the "feet" child object must be a little bit under the player- this is because when the Raycast2d "fires" it will find the FIRST object with a collider it hits- so if you have the start of the raycast hit a collider on the player then it will always show the raycast hitting the player, not a platform. So to get around this have the raycast fire from the feet- and have the feet position a tiny bit below the player. To help with this I added a print statement that will print to the console which object the raycast is hitting, if it doesn't say "Platform" then you need to lower the feet! :)
Furthermore, I'm not sure how you are moving your platforms- but if the Velocity of the platform always prints "0,0" then its because you are moving the platforms position directly, instead of moving it by forces (this happened to me when I was testing this script). I got around this by moving the platform by "AddForce". Also depending on the "Mass" of your platforms, you may need to drastically increase the "xForceDampener" which I should of actually labeled "xForceMultiplier" as I found while testing I needed to set it much higher- like at 60, instead of 0.25 which I previously thought would be okay..
Hope this helped :D
EDIT: Linking the unity docs for 2D Raycasts in case you need
http://docs.unity3d.com/ScriptReference/Physics2D.Raycast.html

Unity - how can I show / hide 3D Text

how can I display 3D text after certain time then hide it after certain time
My tries
public Text text_tap;
GameObject.Find("3dtext").active = true; // first try but it dosnt work
if (Time.time > 5) {
// second try but it I cant attach my 3d text to my script
text_tap.gameObject.SetActive(true);
}
I cant find any thing in 3D documentation
I don't know the exactly problem, but there you have some hints:
If you search in the scene for a GameObject that is deactivated it won't find it. The Gameobject MUST be active for the GameObject.Find() function to work. The easiest thing you can do is to keep the GameObject activated, and if the initial state is for it to stay hidden just hide it in the Awake().
Secondly, seems that you are trying to access a TextMesh object
but you reference in your code a Text object.
If you find a GameObject and request a Component that the GO does not contains, it returns null.
Finally The api to Activate/Deactivate a GameObject (GO) is
myGameobject.SetActive(true)
The one you are using (myGameobject.active = true) is deprecated
Try this example, it should work:
public YourMonoBehaviour : MonoBehaviour
{
public TextMesh text_tap;
float awakeTime;
void Awake()
{
// Remember to activate the GO 3dtext in the scene!
text_tap = GameObject.Find("3dtext").GetComponent<TextMesh>():
awakeTime = Time.time
}
void Update()
{
if ((Time.time - awakeTime) > 5)
{
// second try but it I cant attach my 3d text to my script
text_tap.gameObject.SetActive(true);
}
}
}
If you need to "do something after a delay" you're talking about Coroutines.
Checking Time.time will only check if the game has been running for x time, and using Thread.Sleep in Unity will cause it to delay since you're causing an Update or similar to lock and not return.
Instead, use
yield return WaitForSeconds(5);
text_tap.gameObject.SetActive(false);
As another warning, this code assumes that the target object is not the same gameObject as the one hosting this script, since coroutines do not execute on inactive objects. Similarly, disabling an ancestor (via the scene hierarchy, or transofrm.parent) of a gameObject disables the gameObject itself.
If this is the case, get the component that renders 3d text and disable it instead of the whole gameObject via the enabled field.
you can also use Invoke() to achieve. as explained above note that the text would have to be set by other means than Find cause if it is not active it will not find it.
void Start() //or any event
{
Invoke("ShowTextTap", 5f);//invoke after 5 seconds
}
void ShowTextTap()
{
text_tap.gameObject.SetActive(true);
//then remove it
Invoke("DisableTextTap", 5f);
}
void DisableTextTap()
{
text_tap.gameObject.SetActive(false);
}

Unity 2D c# scripting, Spawnobject at mouseposition when down

I'm fairly new to C#(basically first time using, having to script for this project), I'm trying to teleport (from off screen to on) an object in my game(i'm using a cube for a simple object, in which I will use inkscape to create a 'better' object in its place when it works)will add cube2 later, just focusing on getting this working.
The aim is to teleport an object to where to my 'Bumber' prefab (the floor), based upon the player clicking a position on the 'Bumber' and spawn where the mouse position was on that 'Bumber' and if not on the 'Bumber' don't spawn at all(haven't go to bumber check yet), which will trigger an event, causing the player to lose.
When I was playing the game before, when I clicked, the cube would only despawn and then throw an error at me and not spawn in at the cursors position
I have my 'cube' prefab (dragged from hierarchy into Resources folder, which has the spawn script component). When I go back into unity, I get the error:
(32, 37) the name 'cube' doesn't exist in current context
(32,25) The best overloaded method match for `UnityEngine.Object.Instantiate(UnityEngine.Object, UnityEngine.Vector3, UnityEngine.Quaternion)' has some invalid arguments
(32, 25) Argument #1' cannot convertobject' expression to type `UnityEngine.Object'
I've tried for hours to fix this script, looking at unity database and to no avail.
using UnityEngine;
using System.Collections;
public class Spawn : MonoBehaviour {
public int trapCount;
void Start ()
{
trapCount = 0;
GameObject cube =(GameObject)Instantiate((GameObject)Resources.Load("cube"));
}
void Update ()
{
if (Input.GetMouseButtonDown (0))
{
Spawner ();
trapCount++;
}
}
void Spawner()
{
Vector3 mousePosition = Input.mousePosition;
transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if(trapCount == 0)
{
Instantiate(cube, transform.position, Quaternion.identity); //getting error here, I don't care about rotation value, don't want to rotate at all, but doesn't like it, if it doesn't have anything there.
}
else if (trapCount >= 1)
{
Debug.Log("Trap limit reached!");
}
}
}
C# please, also, if you could, explain what you're doing, thank you kindly!
Always (well, almost always) believe what the error messages tell you.
(32, 37) the name 'cube' doesn't exist in current context
You get this for the line
Instantiate(cube, transform.position, Quaternion.identity);
At that point there is no cube anywhere within the scope of the method. You have your
GameObject cube =(GameObject)Instantiate((GameObject)Resources.Load("cube"));
in your Start() method, but it only exist within that method. It's not a member of the class for example. Making it a member would solve that problem.
And that is more than likely also the cause of the subsequent errors. If it doesn't know what a cube is, it has no idea what to do with it as an argument of Instantiate().
If you're entirely new to C# the biggest favour you could do yourself is to pick up a good book. Unity will allow you to get pretty far by hacking away at it, but there will be a point where there's simply no substitute for learning the language. It will help you tremendously.
Good luck.

Categories