How to add gameobjects via script in the hierarchy in edit mode? - unity3d

I would like to create a menu item that can build a game object with children and components.
I can't use prefabs for the whole objects because I need that the children are separate prefabs.

You can use something like this:
[MenuItem("YOUR_MENU_NAME/YOUR_SUBMENU_NAME/YOUR_METHOD_NAME %&n")]
static void CreateAPrefab()
{
//Parent
GameObject prefab = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath<Object>("Assets/Prefabs/TestPrefab.prefab"));
prefab.name = "TestPrefab";
if(Selection.activeTransform != null)
{
prefab.transform.SetParent(Selection.activeTransform, false);
}
prefab.transform.localPosition = Vector3.zero;
prefab.transform.localEulerAngles = Vector3.zero;
prefab.transform.localScale = Vector3.one;
//Child 1
GameObject prefabChild1 = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadAssetAtPath<Object>("Assets/Prefabs/TestPrefabChild1.prefab"));
prefabChild1.name = "TestPrefabChild";
prefabChild1.transform.SetParent(prefab.transform, false);
prefabChild1.transform.localPosition = Vector3.zero;
prefabChild1.transform.localEulerAngles = Vector3.zero;
prefabChild1.transform.localScale = Vector3.one;
//Child2...
//...
Selection.activeGameObject = prefab;
}
Don't forget to include using UnityEditor; and to either place the script in an Editor/ folder or use #if UNITY_EDITOR / #endif around the parts using the editor methods. Also I added a shortcut to the MenuItem using %&n (Ctrl + Alt + N).
If you need to change the prefabs that compose the instantiated object, you can try to retrieve them all in your project (maybe be and heavy operation depending on your project) as they did here and display a kind of checklist where you select the prefabs needed as children inside an EditorWindow.

Related

How do i get the the tile in front of the player in unity 2d

I'm trying to get all tiles around the player in unity 2d tileset.
What I would like to happen when player presses U I Would like to get all tiles surrounding the player including the one underneath the player or simply the one 1 tile in front of them.
I'm trying to make a farming Game where when the player pulls out an item it will highlight on the tilemap where they are about to place it.
Please note I'm not asking for full code, I just want what ever solution allows me to get tiles near the players position
Edit, found a solution by editing someone elses code but im not sure if there's a better way, if not I would also like this to work based on player rotation currently it places a tile above the player. Code Source https://lukashermann.dev/writing/unity-highlight-tile-in-tilemap-on-mousever/
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Tilemaps;
public class PlayerGrid : MonoBehaviour
{
private Grid grid;
[SerializeField] private Tilemap interactiveMap = null;
[SerializeField] private Tilemap pathMap = null;
[SerializeField] private Tile hoverTile = null;
[SerializeField] private Tile pathTile = null;
public GameObject player;
private Vector3Int previousMousePos = new Vector3Int();
// Start is called before the first frame update
void Start()
{
grid = gameObject.GetComponent<Grid>();
}
// Update is called once per frame
void Update()
{
var px = Mathf.RoundToInt(player.transform.position.x);
var py = Mathf.RoundToInt(player.transform.position.y);
var tilePos = new Vector3Int(px, py, 0);
if (!tilePos.Equals(previousMousePos))
{
interactiveMap.SetTile(previousMousePos, null); // Remove old hoverTile
interactiveMap.SetTile(tilePos, hoverTile);
previousMousePos = tilePos;
}
// Left mouse click -> add path tile
if (Input.GetMouseButton(0))
{
pathMap.SetTile(tilePos, pathTile);
}
// Right mouse click -> remove path tile
if (Input.GetMouseButton(1))
{
pathMap.SetTile(tilePos, null);
}
}
}
try to use the layer field inside the inspector, you can create new Layers inside the Project Manager and there you can easily create Layers like "Background" "Scenery" "Player" "Foreground".. after this you can assign them individually to your Tiles also its important to have different grids otherwise you will not be able to assign different layers to it i hope it worked already

Unity - Prefab with Sub-Elements Expansion Button Missing in Project Panel

I have been following along with a course. In this course a GameObject called "Path (0)" is added, this GameObject then has three sub-GameObjects ("Waypoint (0/1/2)"). In the tutorial, the guy drags the parent GameObject "Path (0)" into a folder called Paths in the Project panel to create a prefab. This prefab is shown with a handle to expand it. He then expands this prefab to see the sub-elements which can be dragged into the Inspector, as shown below (expand button highlighted with red box)
When I perform these operations, the Project panel does not have an expand button on the "Path" prefab (see below)
Why does my prefab object in the Project panel not have these expansion buttons?
Basically, what he does is he creates a script component with enemy prefab.(attached bellow). and the childobject "waypoints" are marks in scene where enemy will move. I uploaded a part of tutorial on youtube, which i will delete once the problem is solved. if youtube dosent delete it. Please help i am half through the tutorial.
https://youtu.be/NGpaHSmktic
public class EnemyPathing : MonoBehaviour {
[SerializeField] List waypoints;
[SerializeField] float moveSpeed = 2f;
int waypointIndex = 0;
void Start()
{
transform.position = waypoints[waypointIndex].transform.position;
}
// Update is called once per frame
void Update()
{
Move();
}
private void Move()
{
if (waypointIndex < -waypoints.Count - 1)
{
var targetPosition = waypoints[waypointIndex].transform.position; // this is where we go to
var movementThisFrame = moveSpeed * Time.deltaTime; // this is how fast we want to go to
transform.position = Vector2.MoveTowards(transform.position, targetPosition, movementThisFrame);
if (transform.position == targetPosition)
{
waypointIndex++;
}
}
else
{
Destroy(gameObject);
}
}
It must be because you don't have the same unity version.
Simply double click on Path0 and it will open it. In the Hierarchy tab, you will see the asset and its elements.
If you drag back Path0 to the scene, its children will appear too.
It's because you're not supposed to drag a child asset away from its parent.
I don't know how it is used in your tutorial, but if needed, you can make a child prefab too by dragging it to the folder (After double clicking on Path0).
Edit :
I don't really know what you can do to have the exact same situation, but here is another way :
-create a tag 'waypoint' and set this tag for Waypoint0, Waypoint1 and Waypoint2 (in your asset, or before creating it).
-In the Start method of your EnemyPathing.cs add this :
this.waypoints = new List<Transform>();
foreach(GameObject g in GameObject.FindGameObjectsWithTag("waypoint"))
{
waypoints.Add(g.transform);
}
So, it will automatically add your waypoints, even if you have more or less than 3 in your scene.

How to shoot particle like projectile?

I made a tank that shoot sphere balls on mouse click.
my C# script:
GameObject prefab;
// Use this for initialization
void Start () {
prefab = Resources.Load("projectile") as GameObject;
}
// Update is called once per frame
void Update() {
if (Input.GetMouseButtonDown(0))
{
GameObject projectile = Instantiate(prefab) as GameObject;
projectile.transform.position = transform.position + Camera.main.transform.forward * 2;
Rigidbody rb = projectile.GetComponent<Rigidbody>();
rb.velocity = Camera.main.transform.forward * 40;
}
}
in this script im shooting a mesh named projectile. But I want to shoot a particle ball and not a mesh. I already tried to change the particle to Orbparticle on script but no object was spawned. What im doing wrong?
No object was spawned because you probably don't have a resource called Orbparticle. Check if you have any errors when you run your script. If Resources.Load doesn't find the object you want by the path you gave it, it will give null, which probably why no object is being spawned.
If you want to shoot a particle instead of a mesh then what you need to do is set prefab to a GameObject you prepared ahead of time that has the ParticleSystem you want. I'd suggest against using Resources.Load for this.
1. Using Resources.Load.
Change your code to this so that it will alert you if it doesn't find the resource:
GameObject prefab;
// Use this for initialization
void Start () {
string name = "OrbParticle";
prefab = Resources.Load<GameObject>(name);
if (prefab == null) {
Debug.Error("Resource with name " + name + " could not be found!");
}
}
// Update is called once per frame
void Update() {
if (Input.GetMouseButtonDown(0))
{
GameObject projectile = Instantiate(prefab) as GameObject;
projectile.transform.position = transform.position + Camera.main.transform.forward * 2;
Rigidbody rb = projectile.GetComponent<Rigidbody>();
rb.velocity = Camera.main.transform.forward * 40;
}
}
Now in order for this to work you need a prefab called "OrbParticle" or whatever string you set the variable name to. Resources.Load looks for items in paths such as Assets/Resources. So you MUST have your "OrbParticle" prefab located in that Resources folder. Unless you have a specific reason for using Resources.Load, I strongly suggest you go with solution 2.
2. Ditching Resources.Load and using the Prefab directly.
Change your code to this:
public GameObject prefab;
// Update is called once per frame
void Update() {
if (Input.GetMouseButtonDown(0))
{
GameObject projectile = Instantiate(prefab) as GameObject;
projectile.transform.position = transform.position + Camera.main.transform.forward * 2;
Rigidbody rb = projectile.GetComponent<Rigidbody>();
rb.velocity = Camera.main.transform.forward * 40;
}
}
Then do this:
Create a new empty GameObject.
Attach a ParticleSystem to the GameObject.
Make a new prefab asset.
Drag and drop the newly created GameObject into a Prefab asset.
Drag and drop the the prefab into prefab field in your Monobehaviour (the object doing the shooting. It will have a prefab field in the Inspector. That's why we set prefab to be a public field).
If you continue having problems, look in Unity's Hierarchy to see if no object is being created at all. It might be the case that it is instantiating a GameObject but the GameObject is invisible for some reason or not instantiating in the location you expect.

How to make Unity UI object draggable when the objects are instantiating at runtime?

I am working on a management game where every user has some specific characters in save files. I am instantiating these characters inside a panel, I want the user to choose one of the cards and drag it to some specific point. I am able to make a drag script for the object that is already in a scene. But how to achieve the same thing if objects are generating at runtime?
I just need some idea how to do it.
here's my current code to drag UI object.
public void OnDrag(){
btn.transform.position = Input.mousePosition;
}
public void EndDrag(){
if (btn.transform.position.x -500 <50 || btn.transform.position.x -500 > -50) {
//btn.transform.position = new Vector3 (-10, 10);
rt.anchoredPosition = new Vector3 (500, 100, 0);
}
else{
rt.anchoredPosition = new Vector3 (-10, -10, 0);
}
}
At the time you Instantiate your GameObject obj, do:
obj.addComponent("YourScript");
where YourScript is your script, which you have written, that attached to a GameObjects makes it draggable..
Alternatively, you instantiate a prefab, attach the script to the prefab through the editor.
This is preferrable because addComponent() will get deprecated in the next versions.
I also recommend to keep a List<YourInstantiatedObjectType> in the parent.

how to randomly initialize particles system in different places of scene in unity3d

I recently tried asking this question but I realized it was not a sufficient question. In my game the player is a fire fighter learner and i want to broke out fire randomly in my game (like not predictable by player), but i did not know how to implement this.
So far i have done this but nothing goes good.(I have a empty object called t in unity which have 3 to 5 particles systems, and all are set to dont awake at start)
code is here :
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
public ParticleSystem[] particles;
public int numOn = 3;
public int j;
void Start() {
for (int i = 0; i < particles.Length - 1; i++) {
j = Random.Range(i + 1, particles.Length - 1);
ParticleSystem t = particles[j];
particles[j] = particles[i];
particles[i] = t;
}
for (j = 0; j < numOn; j++ )
{
particles[j].Play();
}
}
}
help will be appreciated :-)
You could try using prefabs. Create a game object in the editor that has any particle systems and scripts your fire objects need. Once it's good, drag the object from the hierarchy into your project. This will create a prefab (you can now remove it from the scene). Now, on your spawning script, add a field of type GameObject and drag the prefab you made before into it. Now, when you need to create one, just call Instantiate(prefabVar) to create a copy of your prefab.
Edit:
For your specific case, since you only want one fire to be instantiated in a random location, you could have your spawning script look something like this:
public Transform[] SpawnPoints;
public GameObject FirePrefab;
void Start() {
Transform selectedSpawnPoint = SpawnPoints[(int)Random.Range(0, SpawnPoints.Count - 1)];
Instantiate(FirePrefab, selectedSpawnPoint.position, selectedSpawnPoint.rotation);
}
This solution would allow for you to potentially spawn more than one fire object if you needed. An alternative would be if you will only ever have exactly one fire object in the scene at all. Instead of instantiating from a prefab, the object is already in the scene and you just move it to one of your spawn points at the start of the scene. An example script on the fire object itself:
public Transform[] SpawnPoints;
void Start() {
Transform selectedSpawnPoint = SpawnPoints[(int)Random.Range(0, SpawnPoints.Count - 1)];
transform.position = selectedSpawnPoint.position;
transform.rotation = selectedSpawnPoint.rotation;
}