I'm trying to get the position of my camera in cocos3d, but am having trouble. Here's what my initializeWorld looks like
[self addContentFromPODFile: #"leggo.pod"];
CC3Camera* cam2 = (CC3Camera*) [self getNodeNamed:#"Camera"];
[self addChild:cam2];
//the location and rotation is just for testing
//cam2.location = cc3v(0,57.101,71.694);
//cam2.rotation = cc3v(-38,0,0);
CC3Vector camLoc = cam2.location;
NSLog(#"cam2 position is x=%# y=%# z=%#", camLoc.x, camLoc.y, camLoc.z );
Can anyone tell me why the value of camLoc.x, camLoc.y, and camLoc.z are always null? I tried getting the location after a delay, but they are still null. I'm out of ideas. It seemed like I was getting close with this similar issue, but I still can't figure it out. Thanks
They're null because you use the wrong format string. %# is only for id types but the coordinates are simple float values. Instead use this:
NSLog(#"cam2 position is x=%f y=%f z=%f", camLoc.x, camLoc.y, camLoc.z);
PS: learn to use the debugger. If you had set a simple breakpoint and had a look at the local variables you would have seen right away that the values aren't really "null".
Related
Could you please help me to write the right syntax? I am stuck with the following code:
GameObject cube = (GameObject)Instantiate(cube_prefab, new Vector3(x, y, 0), Quaternion.identity, transform);
cube.GetComponentInChildren<TextMeshPro>.text = "test" **// WORKS FINE**
Take into account that inside my prefab i have more TextMeshPro, so my question is: how can I get to the second object if i can't access trought an array ? sounds weird for me
cube.transform.GetChild(0).GetComponent<TextMeshPro>().text = "AAA" // DOESN'T WORK
Thanks in advance
The GetChild(int) method is a method of transform. In your example, you're calling GetChild(0) from the GameObject instead. So the fix in your example would use the transform property of your "cube", find the child, then get the component of the child item:
GameObject cube = (GameObject)Instantiate(cube_prefab, new Vector3(x, y, 0), Quaternion.identity, transform);
cube.GetComponentInChildren<TextMeshPro>.text = "test" **// WORKS FINE**
cube.transform.GetChild(0).GetComponent<TextMeshPro>.text = "test"
Here's the Unity docs for GetChild(int).
If you wanted to iterate over the next level of children for your game object, you could do this:
var t = cube.transform;
var childCount = t.childCount;
for ( int i = 0; i < childCount; i++ )
{
if ( t.GetChild(i).TryGetComponent<TextMeshPro> ( out var tmp ) )
{
tmp.text = $"TextMeshPro found on child {i}";
}
}
Be aware, that this will only iterate over the direct children of "cube", not the children of those children. You would have to check the child count of each child to check further down the family tree.
Sorry if I sound like I'm preaching, but it seems you just try to guess what the syntax is, without knowing what it each thing really does, and it won't do you any good. You should look into methods with generics (especially how to call them) and try to write code meaningfully instead of throwing brackets here and there, and expect things to happen.
With that out of the way, let's look at your issue.
The name 'GetChild' does not exist in the current context, because your cube is of GameObject type, which indeed doesn't have a GetChild method. The component that does have it is Transform. You should call it like: cube.transform.GetChild(0)...
If you fix that, the next issue is that GetChild method doesn't use generics (<Type>) and even if it did, first you provide should provide a type in angle brackets, and then write regular brackets () to indicate method call. What you probably wanted is to first get child, and then to get a component in it: cube.transform.GetChild(0).GetComponent<TextMeshPro>().text = "test";
In cube.GetComponentInChildren<TextMeshPro>.GetChild(0).text you miss brackets: cube.GetComponentInChildren<TextMeshPro>().GetChild(0).text. Morover, the TextMeshPro doesn't have a GetChild method, you must have confused ordering of your method calls.
In cube.GetComponentInChildren<TextMeshPro>[0] you try to use syntax as if you were using arrays, while GetComponentInChildren is just a method, not a property that is an array.
To answer your question shortly: use yourGameObject.transform.GetChild(childIndex).GetComponent<TextMeshPro>().text transform.GetChild() to navigate down to your desired gameObject and only then call GetComponent (remember brackets!) to get to your text property.
the right syntax was
cube.transform.GetChild(0).gameObject.GetComponent().text = "test"
cube.transform.GetChild(1).gameObject.GetComponent().text = "test"
From my research I can see I am getting a vector issue (it looks like I divide by 0 but I don't do an divisions in my script).
I checked every script I have for positions and tried to catch it between trace statements. Couldnt do it. It looks like its in some update or fixed update but I have no clue where.
This error comes up SOMETIMES right as an enemy is killed.
I feel it has something to do with its position. Clicking on this error does nothing, but SOMETIMES it highlights the gameobject that got the bad transform passed to it.
Is there somewhere in your code I could get getting a NAN vector that I can look for?
Right as an enemy dies I will get a lot of these, and once its dead (destroyed) this problem goes away. It will play through a bit of animation, triggering the error each frame, and then when the enemy dies the error stops.
Clicking the error will only highlight the gameobject but will not open to a script where this occurs.
It comes up maybe 1 in 5 times whenever an enemy is killed...
Here is the enemy dying script (it doesn't set positions so the problem likely does not lie here)
public void killSelf()
{
_animator.SetBool("isAttacking",false);
_animator.SetBool("isDead",true);
StartCoroutine(processKillSelf());
}
IEnumerator processKillSelf()
{
yield return new WaitForSeconds(1f);//its a 30 frame animation
Destroy(gameObject);
}
Is there a way to FORCE unity3D to break on this error and let me look up the stack trace?
Not having the stack trace is the only reason I can't find where this is occurring.
I know this is late but I just had a similar problem and maybe it helps someone in the future.
As you already noticed this always happens if somwhere you try to devide a value by 0.
In my case I just couldn't find where I possibly divided by 0 that easy and unfortunately something like
try
{
transform.position = possiblyBrokenVector3;
}
catch
{
}
didn't catch it either so I couldn't set up proper brakepoints since it was called in Update.
What you always can do is actually checking the values for NaN. I directly made it an extension method for checking Vector3:
public static Vector3Extensions
{
public static bool ContainsNaN(this Vector3 vector)
{
return float.IsNaN(vector.x) || float.IsNaN(vector.y) || float.IsNaN(vector.z);
}
}
Now I can always check before I assign like
if(possiblyBrokenVector3.ContainsNaN)
{
Debug.LogWarning("Ignoring a NaN vector here!", this);
}
else
{
transform.position = possiblyBrokenVector3;
}
set a Brakepoint on the Debug line and finally step through the call history to see how the broken input value actually was produced.
Without seeing more of your code I can't say for sure but it sounds like reference is not being updated internally (ie. something is pointing to a vector that has already been destroyed.) I would poke around your animation code to see if that turns up anything.
For what its worth Object.Destroy has an optional second argument that is a delay timer. ( http://docs.unity3d.com/ScriptReference/Object.Destroy.html ) so you could re-write your code like this:
public void killSelf()
{
_animator.SetBool("isAttacking",false);
_animator.SetBool("isDead",true);
Destroy(gameObject, 1f);
}
and totally omit the processKillSelf() coroutine.
I found the problem:
It was not the character, but an HP bar on the character. The local scale of that HP bar was having one of the values set to 0 on death. Making sure the value is at least 0.1f fixed this problem:
float x = _hpBarMaxScale * health/healthmax>0?(_hpBarMaxScale * health/healthmax):0.1f;
hpBar.transform.localScale = new Vector3(x,hpBar.transform.localScale.y,hpBar.transform.localScale.z);
I downloaded JDFlipNumberView from here.
It works but there is a problem with the frame. To change the frame the developer has said to use:
flipNumberView.frame = CGRectMake(10,100,300,100);
but when I do this it doesn't change.
PS: when I put NSLog(#"%#",flipNumberView.frame); it returns null.
How can I change the frame?
"fram' is not a string, it is structure's object.so if you want see frame. you can use it.
NSLog(#"Width = %f",btn.frame.size.width);
NSLog(#"height = %f",btn.frame.size.height);
NSLog(#"x = %f",btn.frame.origin.x);
NSLog(#"y = %f",btn.frame.origin.y);
may be it help for you.
If you use the example project, you need to deactivate the layoutSubviews: method first. It resets the frame on every relayout.
Otherwise just set a new frame.
I am working on map view app.I want know that how we can identify that coordinates are in my current region(Map region that bound with screen) or outside of it.
Thanks In Advance.
You have different options. You can see this sample code from apple: Regions. That, has I understand, check the device position by the antenna's position.
Or tracking device position, and check if is inside a region defined by You. Check this question
If you find a better solution, please let me know.
EDIT:
To check if a coordinate is visible in the map try using this:
// Your coordinates - Lisbon for example
float lisbonLatitudeValue = 38.7069320;
float lisbonLongitudeValue = -9.1356321;
CLLocationCoordinate2D lisbonCoordinates = CLLocationCoordinate2DMake(lisbonLatitudeValue, lisbonLongitudeValue);
if (MKMapRectContainsPoint(mapView.visibleMapRect, MKMapPointForCoordinate(lisbonCoordinates)))
{
// do something
NSLog(#" - Lisbon is visible");
}
else {
// do something
NSLog(#" - Lisbon is not visible");
}
Hope it helps
I am looking for a way to find the filename of the CGSprite variable, then use it in an IF statement. Like this:
if(target.spritefilename?? == #"Car1.png")
{
target = [CCSprite spriteWithFile:#"Car1_dead.png" rect:CGRectMake(0, 0, 37, 76)];
}
I am not sure why you want to do this. But as far as I am guessing your purpose I would like to suggest an alternative and proper way to identify your different sprites.
There is a "userData" property in the sprite (inherited from parent) which you can use to store your custom data. So when you create your sprites you should also assign the identified to the userData property.
Like in your case when you first create your "target" sprite, you can then set, "target.userData = "
Later you can check if target.userData is equal to your required file name.
This is the proper way to store custom data in your sprites.
I hope it helps.
if([target.spritefilename isEqualtoString:#"Car1.png"])
is what i guess you are looking for.
You can use isEqualtoString for string comparison.
if([target.spritefilename isEqualtoString:#"Car1.png"])
For NSString.
store the sprite names in an array and check the current sprite name matches the name in an array.
if([image_array containsObject:#"car.png"])
{
NSLog(#"Image Found");
}
Hope this helps!!!
If([sprite.userData hasPrefix#"Car1"])
...
if([(NSString*)sprite.userData hasPrefix#"Car1"])
...
If the purpose of this to just identifying the sprite you can simply do it by using tag property of sprite.
Like set a taf for sprite while initialing or creating the sprite as
CCSprite *spr1=[CCSprite spriteWithFile:#"1.png"];
spr1.tag=1;
CCSprite *spr2=[CCSprite spriteWithFile:#"2.png"];
spr2.tag=2;
and while getting the sprite on particular event use to get tag value as
if([(CCSprite*)tagetSprite tag]==1)
{
}
else if([(CCSprite*)tagetSprite tag]==2)
{
}