Unity Instantiate objects appear in hierarchy but not visible - visual-studio

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MakePipe : MonoBehaviour
{
public GameObject pipe;
float timer = 0;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
timer += Time.deltaTime;
if (timer > 1)
{
Instantiate(pipe);
timer = 0;
}
}
}
I am trying to instantiate pipes using prefab, and with the code, a new set of pipes should spawn and move left from the original position where the first set of pipes spawned, but they are not visible.
They are generated as clones in the hierarchy, but when I double-click them to check the position, it points towards the first pipe position.
My guess is that new clones are generated and overlapped in the first pipe as they move together.
Please help
Thanks for your reply.
Sorry I didn't add a separate cs code 'move', I should have added gif..
The following code is to move the pipe left with certain speed. There is no problem there.
However from the 'MakePipe' code that I originally posted, I used instantiate to keep reproducing the pipe. Maybe I should add some lines to 'Start()' part to set original spawn location?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
public float speed;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.position += Vector3.left * speed * Time.deltaTime;
// Debug.Log(transform.position);
}
}
I had to delete photos because error message tells me I should have more than 10 reps to edit :(

I don't have enough rep to comment, I'll attempt to give you a answer and update it for what you need.
The Object.Instantiate method has some parameters that you can use to get your pipes into place.
public static Object Instantiate(Object original, Vector3 position, Quaternion rotation, Transform parent);
And without the overloads it will use the original prefab's parameters. So they will spawn in the same location. You have to calculate the next position and pass it in the Instantiate method (Vector3 position).
I misunderstood what you are trying to do at first. #Geeky Quentin
gave the right answer in the first comment.
[SerializeField] private GameObject pipe;
float timer = 0;
float offset = 1.5f;
void Start()
{
}
void Update()
{
timer += Time.deltaTime;
transform.position += new Vector3(-Time.deltaTime/offset, 0, 0);
if (timer > 1)
{
GameObject lastPipe = Instantiate(pipe);
lastPipe.transform.SetParent(transform);
timer = 0;
}
}
I still don't have enough rep to comment. Regarding your last changes. I tested your code out.
Are you parenting the instantiated pipe to the PipeMaker in another script? If not this is the effect it spawns but it does not move:
To make it work you need to parent the instantiated pipe and change it's position MakePipe.cs:
public GameObject pipe;
float timer = 0;
private GameObject _newPipe;
void Update()
{
timer += Time.deltaTime;
if (timer > 1)
{
//instatiate with parent on transform
_newPipe = Instantiate(pipe, transform);
//Set positiion to orginal prefab position
_newPipe.transform.position = pipe.transform.position;
timer = 0;
}
}
This is the effect:
My PipeSpawner has the Move and MakePipe scripts attached to it. And the prefab is in a hidden PipePrefab object that's unrelated to the rest of the system.
You could also set the position of the original spawn location in your Start() method as you said, it's up to you.

Related

Moving a Prefab in Unity

The purpose of the code is to
make a prefab of "Normal" and "Virus"
make them move in random directions
when they collide, change "Normal" into "Virus" Prefabs
However, I've got stucked on step 2.
I successfuly made "Normal" and "Virus" Prefabs get spawned at random places.
Btw, I have no idea what I should do to supply transform function to Prefabs.
Also, what codes should I use to replace "Normal" Prefabs into "Virus" Prefabs if they collide each other?
These are the codes and pics I used
using UnityEngine;
public class VirusSpawner : MonoBehaviour
{
[SerializeField]
private int objectSpawnCount = 5;
[SerializeField]
private GameObject[] prefabArray;
private void Awake()
{
for (int i = 0; i < objectSpawnCount; ++i)
{
int index = Random.Range(0, prefabArray.Length);
float x = Random.Range(-3, 3);
float y = Random.Range(-4, 4);
Vector3 position = new Vector3(x, y, 0);
Instantiate(prefabArray[index], position, Quaternion.identity);
}
}
}
As I understood what you need is a script for your objects, responsible for moving them and controlling all this "Normal" and "Virus" states.
2.1. Create a C# Script (i.e. "Virus") that moves the object as soon as it exists.
2.2. Right after instantiating your prefabs add this script to it:
GameObject newGO = Instantiate(prefabArray[index], position, Quaternion.identity);
newGO.AddComponent<Virus>();
On the new "Virus" script, add the collision detection and variable that holds the state of Normal or Virus
As #Caio Rocha said you can instantiate new Virus Object and add component to it but there can be one more way which can be faster :
Create a Empty Game Object.
Add both (Virus and Normal) prefabs as children of that prefab and drag and drop to project window to create new Prefab.
Attach this script to Parent:
public class ParentObject : MonoBehaviour
{
public GameObject VirusObject;
public GameObject NormalObject;
private bool isVirus;
private void Awake()
{
isVirus = (Random.Range(0, 2) == 1); //Randomly Make an object
//virus or normal on instantiation
if (isVirus)
{
TurnToVirus();
}
else
{
TurntoNormal();
}
}
private void OnCollisionEnter(Collision other)
{
ParentObject coll =
other.collider.gameObject.GetComponent<ParentObject>();
if (coll && coll.isVirus) //if other object is virus
{
TurnToVirus();
}
}
private void TurnToVirus()
{
VirusObject.SetActive(true);
NormalObject.SetActive(false);
}
private void TurntoNormal()
{
VirusObject.SetActive(false);
NormalObject.SetActive(true);
}
}
Now Inside prefab array move this Parent prefab instead of your own prefabs and it will randomly create normal and virus objects and when they interact normal turn to viruses. Make sure this script and collider is now on parent. This is much optimized over adding component individually just for single check.

How to move a cube 3 second in one direction, and next 3 seconds in oppposite direction, alternatively

I am new to unity, and trying something like below, but I can either move only in one direction, or not moving at all.
My cube is a trigger, and is not using gravity. I have checked the Kitematic box. I am trying to make the cube move to and fro, so that player have difficuly collecting it.
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
public class movedanger : MonoBehaviour
{
private int mytime = 0;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
MyMover(mytime);
}
void MyMover(int mytime)
{
if (mytime <= 3)
{
transform.Translate(Vector3.forward * Time.deltaTime);
mytime++;
}
else
{
transform.Translate(-Vector3.forward * Time.deltaTime);
mytime = 1;
}
}
}
What you are looking for is to and fro movement of an object. You can achieve this with Mathf.PingPong() function instead of using translate. I have tested it with a cube, you can set the minimum and maximum distance it should move to and the speed at which it travels. Since you want the cube to move 3 seconds in one direction at a time. You can calculate the speed as distance/time so the max distance it should travel to from the current distance and the time (3 seconds) it takes. Hope this helps.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCube : MonoBehaviour {
public float min = 2f;
public float max = 8f;
public float SpeedOfMovement = 2f;
// Start is called before the first frame update
void Start () {
}
// Update is called once per frame
void Update () {
transform.position = new Vector3 (Mathf.PingPong (Time.time * SpeedOfMovement, max - min) + min, transform.position.y, transform.position.z);
}
}
With InvokeRepeating you will call the same MoveCube method every 3 seconds.
using UnityEngine;
public class MoveDanger: MonoBehaviour
{
public bool isForward = false;
private void Start()
{
InvokeRepeating("MoveCube", 0f, 3f);
}
private void MoveCube()
{
if (isForward)
{
transform.Translate(Vector3.back);
isForward = false;
}
else
{
transform.Translate(Vector3.forward);
isForward = true;
}
}
}
Honestly the best and easiest way to do something like this, once you get used to it, is just to
Use Unity's incredibly simple animator system:
(Essentially just click "new animation" and then drag the object around as you want it animated.)
There are 100s of tutorials online explaining how to use it.
It's one of those things where once you use it and see how easy it is, you will do a "facepalm" and never bother again with other ways.
It's really "the Unity way" to achieve the goal here, dead easy and flexible.

Can I make my enemy run towards the player faster in this code? (Unity)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Enemy : MonoBehaviour
{
public NavMeshAgent Ninja;
public GameObject Player;
public float NinjaDistanceRun = 30.0f;
void Start()
{
Ninja = GetComponent<NavMeshAgent>();
}
void Update()
{
float distance = Vector3.Distance(transform.position, Player.transform.position);
//Run towards player
if(distance < NinjaDistanceRun)
{
Vector3 dirToPlayer = transform.position - Player.transform.position;
Vector3 newPos = transform.position - dirToPlayer;
Ninja.SetDestination(newPos);
}
}
}
The code shown above is what I use to make the enemy follow the player when in range. Can I make my enemy go faster without trashing this whole script and making a new one that has a different line of thought?
Set the maximum speed for your ninja(NavMeshAgent.speed). Here is the documentation for more information:
https://docs.unity3d.com/ScriptReference/AI.NavMeshAgent-speed.html
In the START method you can set a new speed to your Navmesh agent, and this character will walk or run in the player direction.

Use parameters for variable animation

I'd like to animate my Score-GUI text counting up to a variable value but there are two things in my way:
1: How can I animate to a variable instead of a fixed value?
2: Why can't I add own properties (like int) to my script and animate them?
For #2 I created a property in my script. Yet the editor won't show it in the AddProperty-dialog (as shown below):
public int currentScore = 0;
public int score {
get { return currentScore; }
set { this.currentScore += value; }
}
EDIT: The animator is set up in the most basic way:
Since you only have 1 Animation. An Animator is irrelevant to the solution. This is tested and working. Now you need to make the Animation a Legacy type to get this working because we are not going to use the Animator.
Click the Animation on the Project -> look at the upper right section of the Inspector view, there is a little button there which will drop down a selection. "Debug" then Check the Legacy.
Set your Animation to whatever you want. I force the WrapMode in the script to be wrap mode once. So it will only play once.
Now in the Animation Component make sure you select the Animation that you want by default or it wont work. Cause we only use anim.Play(); Without parameters meaning, run the default animation that is set.
I created a Text UI and added an Animation that alpha is 0 from the start and at the end point making it 1. You have to do that on your own.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class MyScore : MonoBehaviour {
// Use this for initialization
public int currentScore = 0;
public GameObject Myscore; // Drag the GameObject that has the Animation for your score.
public Text myScoreText; //Drag in the Inspector the Text object to reference
public Animation anim;
public int score
{
get { return currentScore; }
set { this.currentScore += value; }
}
void Start()
{
anim = Myscore.GetComponent<Animation>(); // Reference the Animation Component.
anim.wrapMode = WrapMode.Once; // Legacy animation Set to play once
AddScore();
}
public void AddScore()
{
score += 10;
myScoreText.text = score.ToString();
anim.Play();
Debug.Log("Current Score is "+ score);
Invoke("AddScore", 2);
}
}
Good luck.

Animate/move/translate/tween image in Unity 4.6 from C# code

How can I move/animate/translate/tween an Image from position A to position B using C# code in Unity 4.6?
Assuming Image is a GameObject, so it could be a Button or whatever.
There has to be a one-liner for this, right? I've been googling for a while but all I can see out-of-the-box is stuff done in Update, and I firmly believe doing stuff in Update is not a fast way of scripting things.
maZZZu's method will work, however, if you do NOT want to use the Update function, you can use an IEnumerator/Coroutine like so…
//Target object that we want to move to
public Transform target;
//Time you want it to take before it reaches the object
public float moveDuration = 1.0f;
void Start ()
{
//Start a coroutine (needed to call a method that returns an IEnumerator
StartCoroutine (Tween (target.position));
}
//IEnumerator return method that takes in the targets position
IEnumerator Tween (Vector3 targetPosition)
{
//Obtain the previous position (original position) of the gameobject this script is attached to
Vector3 previousPosition = gameObject.transform.position;
//Create a time variable
float time = 0.0f;
do
{
//Add the deltaTime to the time variable
time += Time.deltaTime;
//Lerp the gameobject's position that this script is attached to. Lerp takes in the original position, target position and the time to execute it in
gameObject.transform.position = Vector3.Lerp (previousPosition, targetPosition, time / moveDuration);
yield return 0;
//Do the Lerp function while to time is less than the move duration.
} while (time < moveDuration);
}
This script will need to be attached to the GameObject that you would like to move. You will then need to create another GameObject in the scene that will be your Target…
The code is commented but if you need clarification on something just post a comment here.
If you want to do the movement yourself you can use something like this:
public Vector3 targetPosition = new Vector3(100, 0, 0);
public float speed = 10.0f;
public float threshold = 0.5f;
void Update () {
Vector3 direction = targetPosition - transform.position;
if(direction.magnitude > threshold){
direction.Normalize();
transform.position = transform.position + direction * speed * Time.deltaTime;
}else{
// Without this game object jumps around target and never settles
transform.position = targetPosition;
}
}
Or you can download for example DOTween package and just start the tween:
public Vector3 targetPosition = new Vector3(100, 0, 0);
public float tweenTime = 10.0f;
void Start () {
DOTween.Init(false, false, LogBehaviour.Default);
transform.DOMove(targetPosition, tweenTime);
}

Resources