Unity3D Instantiating as GameObject - object

My code look like that:
if (Input.GetButtonDown ("Fire2")) {
GameObject transparent = Instantiate (building, new Vector3 (0, -10,0), Quaternion.identity) as GameObject;
}
Where building is public GameObject which I add through unity
Inpsector. After using right click GameObject is instantiated, but
transparent variable has null instead of the instantiated GameObject.
If I change type of transparent to Object and I remove 'as GameObject'
cast, everything works good.
Ok, I find out what was wrong. My building wasn't GameObject, it was Building (class which inherits MonoBehaviour, so have gameobject in itself). Now I instantiate building.gameobject and everything is ok.

It turned out that I initiated 'building' as a Building class (Building is my own class and inherits MonoBehaviour), not as a GameObject so unity had problem to put Building into GameObject. It's looks like that now:
if (Input.GetButtonDown ("Fire2")) {
GameObject transparent = Instantiate (building.gameobject, new Vector3 (0, -10,0), Quaternion.identity) as GameObject;
}

Related

How to set the object coordinates so that they are above the marker?

Before that, i apologize if my english is bad.
I made an AR about crystal structure. I will make an AR with 36 crystal structure objects with 9 markers/image target which means 1 marker has 4 objects to be displayed. The concept that I want to make is that these objects are connected to the spawn and destroy system and I managed to make it with the help of tutorials on youtube. but I have a problem, my AR object doesn't want to be on top of the marker/image tergets. if I try to adjust the position of the object, when I try to run it happens that the object is still next to the marker and follows the 0,0,0 coordinates of the object which is not above the marker, even though I have already inserted the object into the marker. I am very confused how to solve my problem.
this is part script for my project to spawn and destroy system:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sistem : MonoBehaviour
{
public static Sistem instance;
public int ID;
public GameObject TempatSpawn;
public GameObject[] KoleksiStruktur;
// Start is called before the first frame update
void Awake()
{
instance = this;
}
void Start()
{
SpawnObject();
}
public void SpawnObject()
{
GameObject Benda = Instantiate(KoleksiStruktur[ID]);
Benda.transform.SetParent(TempatSpawn.transform, false);
Benda.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
Debug.Log("Objek berhasil di-instantiate");
}
}
the object and the marker/image target
i tried to solve the problem by setting the object over the marker but still can't fix it. I hope to find a solution how I can display my object above the marker.

Adding a gameObject in an object in Unity3D

The question might seem a little too weird but I want to add the object "Capsule" to my gameobject using script (see the photo below)
This is my code for adding components in my object:
object1 = (GameObject)Resources.Load (name) as GameObject;
myObject = Instantiate (object1);
myObject.transform.SetParent (parent.transform);
myObject.transform.position = new Vector3 (0, 0, 0);
myObject.transform.localScale = new Vector3 (70f, 70f, 70f);
myObject.AddComponent<BoxCollider> ();
myObject.AddComponent<CapsuleCollider> ();
myObject.AddComponent<MeshRenderer> ();
myObject.gameObject.SetActive (true);
What could be the possible solution for this? Thank you very much!
There seems to be a misunderstanding of what "Adding a GameObject" means so lets break this down. In Unity, a GameObject is a Transform and a collection of "Components". That Transform can be the "parent" or "child" of another Transform. GameObjects and their "Transform Heirarchy" are what's displayed in the "Heirarchy" Unity window. A single GameObject and its "Components" (things that implement MonoBehaviour) are what's displayed in the the "Inspector" Unity window.
By these terms, you cannot "Add a GameObject to another GameObject" however you can "Add a GameObject as a child of another GameObject" by parenting one Transform to another.
It seems like what you're trying to do here is add your "Capsule" as a child of each of your GameObjects. All you need to do in this case is, for each GameObject, instantiate a new instance of the "Capsule" (it could be setup as a prefab) and parent it to your GameObjects:
public class CapsuleAdder : MonoBehaviour {
private const string capsulePrefabName = "whatever"; // Prefab name goes here
void Awake() {
GameObject newCapsule = Instantiate(Resources.Load(capsulePrefabName) as GameObject) as GameObject;
newCapsule.transform.SetParent(transform); // Sets parent to this
}
}
As long as you properly set capsulePrefabName, any GameObject with this script attached will spawn a copy of your capsule prefab as a child.

Unity - Detecting keyboard input

I'm fairly new to Unity and have been looking up tons of tutorials/guides online. My issue is that for some reason when I use the below code it doesn't detect if the keyboard is clicked. Maybe I am doing keyboard detection wrong. Here is my code:
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
Vector3 player = GameObject.FindGameObjectWithTag("Player").transform.position;
void Update () {
if (Input.GetKeyDown(KeyCode.D)) {
player.x += 0.01F;
}
}
}
Your input code is correct but still couple of things that are not at right place. First you wrote an initializer (static method) outside any function. Remember when you do it in Unity3d C# then it will always give you a warning/error.
If you are using C# don't use this function in the constructor or field initializers, Instead move initialization to the Awake or Start function.
So first move that sort of lines in either functions.
Second thing you are getting Vector3 and trying to use it as reference, that means you got a position reference in form of Vector3 and every change made in that variable will be effective, that is not the case, it won't.
But yes you can do it by getting Transform or GameObject, they will do it for you.
Third and last thing, you are trying to alter Vector3 component ("x" in your case ) directly, that'd also not acceptable for Unity. What you can do is either assign position with new Vector3 or create a separate Vector3 variable, alter that, then assign it to position.
So after all of these addresses your code should be look like this,
using UnityEngine;
using System.Collections;
public class NewBehaviourScript : MonoBehaviour
{
Transform player;
// Use this for initialization
void Start ()
{
player = GameObject.FindGameObjectWithTag ("Player").transform;
}
// Update is called once per frame
void Update ()
{
if (Input.GetKeyDown (KeyCode.D)) {
// Remove one of these two implementations of changing position
// Either
Vector3 newPosition = player.position;
newPosition.x += 0.01f;
player.position = newPosition;
//Or
player.position = new Vector3 (player.position.x + 0.01f, player.position.y, player.position.z);
}
}
}

How to move a HaxeFlixel FlxNapeSprite?

I'm trying to use Nape with HaxeFlixel. Sadly, there's almost no documentation on how to use the addons.nape package and I just can't figure out why this code isn't moving the white rectangle (_test). (I left out imports for simplicity)
class PlayState extends FlxNapeState
{
var _test = new FlxNapeSprite(16, 16);
override public function create():Void
{
super.create();
_test.makeGraphic(16, 16);
_test.body.type = BodyType.KINEMATIC;
add(_test);
}
override public function update():Void
{
_test.body.velocity.x = 100;
super.update();
}
}
There are two issues with your code:
Directly initializing the _test variable leads to the FlxNapeSprite constructor call happening in the constructor of your PlayState. create() is called after the state constructor. This can cause crashes and otherwise weird behavior since Flixel does its internal cleanup between the constructor call of the new state and create() (graphics are disposed, for example, and in this case the Nape Space instance doesn't exist yet since it's created in the super.create() call).
The FlxNapeSprite constructor has a createRectangularBody argument which defaults to true and calls the function of that same name if true. Since you're not passing any asset to the constructor, it ends up creating a Shape with a width and height of 0. This leads to the following error:
Error: Cannot simulate with an invalid Polygon
Instead, you'll want to call createRectangularBody() manually after makeGraphic() to create a Shape that matches the graphic's dimensions.
The complete, working code looks like this:
package;
import flixel.addons.nape.FlxNapeSprite;
import flixel.addons.nape.FlxNapeState;
class PlayState extends FlxNapeState
{
override public function create():Void
{
super.create();
var _test = new FlxNapeSprite(16, 16);
_test.makeGraphic(16, 16);
_test.createRectangularBody();
_test.body.velocity.x = 100;
add(_test);
}
}
Regarding documentation, the FlxNape demo is a great resource to learn from.

QML memory management

I'm trying to test QML to understand how it works with C++. I have ClassA and ClassB - 2 similar C++ classes. Here is a ClassA. All methods are self explanatory with their names, so I won't place implementation here.
class ClassB;
class ClassA : public QObject
{
Q_OBJECT
public:
explicit ClassA(QObject *parent = 0);
~ClassA();
Q_PROPERTY(ClassB* classB READ getClassB WRITE setClassB NOTIFY classBChanged)
ClassB* getClassB() const;
void setClassB(ClassB *classB);
signals:
void classBChanged();
private:
ClassB *m_classB;
};
ClassB is the same, just change all *lassA* to *lassB* and all *lassB* to *lassA*.
Then I register both classed in QML with
qmlRegisterType<ClassA>("testmodule.test",1,0,"ClassA");
qmlRegisterType<ClassB>("testmodule.test",1,0,"ClassB");
And in QML code on mouse click I create both objects like this:
onClicked: {
var comp = Qt.createComponent("TClassA.qml"); //TClassA.qml is
//a component of type
//ClassA
var ca = comp.createObject();
comp = Qt.createComponent("TClassB.qml");
var cb = comp.createObject();
ca.classB = cb;
cb.classA = ca;
parent.blockFromGC = ca;
}
And after that I call garbage collector with gc(). I expected that ca is blocked from removal with parent.blockFromGC and cb is blocked from removal with reference from ca. But garbage collector destroyed cb and after that parent.blockFromGC.classB === null.
So I have second MouseArea with this code:
onClicked: {
console.log(mouse.button)
// if (mouse.button == Qt.RightButton) {
// console.log(parent.vasya.classB)
// }
gc();
console.log(parent.blockFromGC.classB) //I use cb here
}
So when I click the MouseArea I get in console:
qml: 1 //Left button
qml: null //value of parent.blockFromGC.classB
classB destroyed: TQMLClassB(0x34960d0) //I have qDebug() in destructor
So my object cb was destroyed.
So I have this questions:
1) Is there a way how I can register a C++ type as basic type, so I could
write var ca = new ClassA() instead of creating a *.qml file, creating a component and finally creating an object?
2) Why did garbage collector destroyed my cb object and what should I do
to keep this object from deleting?
Moreover! If I uncomment those commented lines
// if (mouse.button == Qt.RightButton) {
// console.log(parent.vasya.classB)
// }
regardless the button I press, the object is not destroyed anymore.
qml: 1 //left button
qml: TQMLClassB(0x3df8e90) //object is alive
.....
qml: 2 //right button
qml: TQMLClassB(0x3df8e90) //before gc() - alive
qml: TQMLClassB(0x3df8e90) //after gc() - alive
3) Where can I read about QML memory management in detailes? I find this behaviour really strange..
Addition 1: I played with this situation a bit more and the results were unpredictable. I updated from 5.3 to Qt 5.4 and this behavior with object deletion has gone. The problem is that the behavior was so unpredictable, that the fact I can't reproduce this behavior in Qt 5.4 doesn't mean that the problem is fixed. I'll try to look in bug reports and bug fixes. If I found something, I'll post it here. If not, I'll try to reproduce this situation in Qt 5.4 and post a report.
Like any QML type, you can define a component statically within another:
Component {
id: classAComponent
ClassA { }
}
onClicked {
var ca = classAComponent.createObject()
}
There is a subtlety here: assigning a QML object to a QML property will increase its JavaScript ref-count. But an instance stored only in the Q_PROPERTY of a C++ object won't be marked by the garbage collector.
QML has a dual ownership system. First it defines a hierarchy of QObject/QQuickItem used for display and ownership. Attached to this backbone is a garbage collection system where any QML object can own a tree of JavaScript objects through property var.
So to keep your ClassB object alive, you either have to keep it in a QML property, or provide a parent for it when calling component.createObject() (it's a hard ownership; it will be destroyed regardless of any JS reference to it when the parent is destroyed)
Example with the QML property:
Component {
id: classAComponent
ClassA {
property Item refClassB
}
}
onClicked {
var ca = classAComponent.createObject()
ca.refClassB = classBComponent.createObject()
}
Ideally you should avoid dynamically creating object as much as possible and use your C++ objects statically like normal QML components and let the declarative structure maintain the QObject backbone automatically, like this:
ClassA {
classB: ClassB { }
}
Sadly not so much, the best I know of, more for QML than C++ is Dynamic QML Object Creation from JavaScript.

Resources