I have written code for a game in which some birds are flying. I created array of CCSprite and added them on Scene. Now it assign a scheduler to each bird object for moving in random direction in screen. All are working. Now i am getting trouble in getting collision in birds.
i am trying to run a CCARRAY_FOREACH loop on array but its giving error.
0xC0000005: Access violation reading location 0xfeeefeee.
Please help me how i can get get collision detection in array element while they are moving. updateCollison method is not executing.
My Code is:
#include "HelloWorldScene.h"
using namespace cocos2d;
CCScene* HelloWorld::scene()
{
CCScene * scene = NULL;
do
{
// 'scene' is an autorelease object
scene = CCScene::create();
CC_BREAK_IF(! scene);
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();
CC_BREAK_IF(! layer);
// add layer as a child to scene
scene->addChild(layer);
} while (0);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//srand(time(NULL));
CCSize size = CCDirector::sharedDirector()->getWinSize();
birds = CCArray::create();
for(int j = 0; j<5; j++){
CCSprite *bird = CCSprite::create("twitter_square.png");
bird->setTag(j);
int max = rand() % 480;
int min = rand() % 320;
bird->setPosition(ccp(max, min));
this->addChild(bird);
birds->addObject(bird);
bird->schedule( schedule_selector(HelloWorld::moveBird), 5.0 );
bird->schedule( schedule_selector(HelloWorld::updateCollison), 5.0 );
}
return true;
}
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
CCDirector::sharedDirector()->end();
}
void HelloWorld::moveBird(float dt)
{
CCSize size = CCDirector::sharedDirector()->getWinSize();
int max = rand() % (int)size.width;
int min = rand() % (int)size.height;
CCActionInterval* actionTo = CCMoveTo::actionWithDuration(5, ccp(max,min));
this->runAction(actionTo);
}
void HelloWorld::updateCollison(float dt)
{
CCObject *obj;
for(int i=0; i < birds->count(); i++)
{
CCLOG("$$$$$$$$$$$$$$$$$$$$$$$");
}
}
It's better to do things in one update function ...for example make one update in that call MoveBird Function which will contain your moving bird code
Secondly now call check Collision function
void update (float dt) {
MoveBird(); // Move how many birds you want to move
CheckCollision();
}
Now how to check collision of your birds
In your collision function forLoop your birds Array check
if(mBirdsArray[i]->boundingBox().containsPoint(mBirdsArray[j]->getPosition()))
and vice versa ...
I hope this will work .. .there maybe better logic than this ..
Related
Okay so I'm making a photography game where when you 'take a photo', Unity sends a few raycasts forward to check if certain tagged items are in the photo (all within the cameras FOV). My problem is, this seems to work intermittently! Sometimes it finds the tagged objects, other times it will be right in front of the view yet it will miss it completely! Can anyone advise about what I'm doing wrong?
public static Transform target;
public static GameObject[] targetName;
public static float length = 250f;
public static Transform thisObject;
// Start is called before the first frame update
void Start()
{
thisObject = GameObject.Find("Main Camera").GetComponent<Transform>();
//target = GameObject.FindGameObjectWithTag("Trees").transform;
}
// Update is called once per frame
void Update()
{
//InFront();
//HasLineOfSight("Trees");
}
public static bool InFront(Transform target1)
{
Vector3 directionToTarget = thisObject.position - target1.position;
float angleOnXAxis = Vector3.Angle(thisObject.right, directionToTarget);
float angleOnYAxis = Vector3.Angle(thisObject.up, directionToTarget);
//Debug.Log(angleOnYAxis);
if (Mathf.Abs(angleOnXAxis) < 130 && Mathf.Abs(angleOnXAxis) > 50
&& Mathf.Abs(angleOnYAxis) < 115 && Mathf.Abs(angleOnYAxis) > 62)
{
//Debug.DrawLine(transform.position, target.position, Color.green);
return true;
}
return false;
}
public static bool HasLineOfSight(string objectTag)
{
RaycastHit hit;
Vector3 direction = target.position - thisObject.position;
//Debug.Log(direction);
if (Physics.Raycast(thisObject.position, direction, out hit, length))
{
if (hit.transform.tag == objectTag)
{
Debug.DrawRay(thisObject.position, direction * 0.96f, Color.red);
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
public static GameObject SortObjects(string objectTag)
{
targetName = GameObject.FindGameObjectsWithTag(objectTag);
GameObject closestObject = null;
for (int i = 0; i < targetName.Length; i++)
{
if (Vector3.Distance(thisObject.position,
targetName[i].transform.position) <= length)
{
if (InFront(targetName[i].transform))
{
if (closestObject == null)
{
closestObject = targetName[i];
}
else
{
if (Vector3.Distance(targetName[i].transform.position, thisObject.position) <= Vector3.Distance(closestObject.transform.position, thisObject.position))
{
closestObject = targetName[i];
}
}
}
}
}
return closestObject;
}
public static bool ObjectCheck(string objectTag)
{
//Debug.Log(SortObjects(objectTag));
if (SortObjects(objectTag) != null)
{
target = SortObjects(objectTag).transform;
//Debug.Log(target);
if (InFront(target) && HasLineOfSight(objectTag))
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
I'm essentially calling ObjectCheck() with the tag I want to check for to get the closest, visible, object with that tag. What is wrong with this code??
In your script, only the closest object to the main camera gets checked. SortObjects() determines the closest tagged object, and then you only handle that single object in ObjectCheck(). - That object might be obstructed by something else, so the method returns false. And other tagged objects that are actually visible, are not picked up this way...
So, you could rename and change your SortObjects() function to check for both conditions right in the loop (InFront(target) && HasLineOfSight(objectTag)), and filter the objects out right in there, since only those objects are of interest.
Also, your HasLineOfSight() method checks the tag of the hit object, but what you probably wanted to do, is to check if the raycast actually hits that exact object. So it should instead compare the hit's gameObject to the target's gameObject, ignoring the tag, since a correct tag alone isn't enough. (Side note: it would make sense to place all "photographable objects" on a "photo layer", and set the layer mask in the Physics.Raycast() call accordingly, it's more efficient that way in larger scenes.)
The way the angles are calculated in the InFront() method is probably causing issues, because the direction vector to the target is really in 3D. To calculate the angles, you could try to use Vector3.Project() or Vector3.ProjectOnPlane(), but that will also be problematic, because of perspective camera issues.
This check is strongly related to the topic of "frustum culling", a technique usually used for rendering. But it's similar to what you need, to filter out all the (possibly) visible objects in the camera's field of view (frustum culling doesn't handle obstruction, it is just a geometric check to see if a point lies within the camera's frustum space). See:
https://en.wikipedia.org/wiki/Viewing_frustum
https://en.wikipedia.org/wiki/Hidden-surface_determination#Viewing-
http://www.lighthouse3d.com/tutorials/view-frustum-culling/
https://docs.unity3d.com/Manual/UnderstandingFrustum.html
If you want to dig deeper and optimize this, there are a couple of ways this can be done. But luckily, Unity comes with many useful related functions already built into the Camera class. So instead, you could use Camera.WorldToScreenPoint() (or Camera.WorldToViewportPoint()), and compare the resulting screen coordinates to the screen size or viewport, like discussed in Unity forum. (The frustum math is hidden behind these compact functions, but beware that this is probably not the optimal way to do this.)
Instead of calling FindGameObjectsWithTag() every time, you could do it only once in Start(), assuming objects do not get created/destroyed while the game is running.
I've tried to modify your script, since I'm also learning Unity again... The script can be dragged to the main camera, and it should show the "focus object" in the Scene view with the green debug line. I hope this helps:
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class PhotoCast : MonoBehaviour
{
public float maxDistance = 250.0f;
public string objectTag = "photo";
protected GameObject[] objs;
protected GameObject objFocus;
protected Camera cam;
public void Start() {
objs = GameObject.FindGameObjectsWithTag(objectTag);
cam = GetComponent<Camera>();
}
public void Update() {
if (Input.GetButtonDown("Fire1")) {
objFocus = CheckObjects();
if (objFocus) {
Debug.Log("closest object in view: " + objFocus.name);
/* TODO: take actual photo here */
}
}
if (objFocus) {
Debug.DrawLine(transform.position,
objFocus.transform.position, Color.green);
}
}
GameObject CheckObjects() {
GameObject obj_closest = null;
float dist_closest = float.MaxValue;
foreach (GameObject o in objs) {
float dist = Vector3.Distance(
o.transform.position, transform.position);
if (dist < maxDistance && dist < dist_closest
&& InViewport(o.transform.position)
&& HasLineOfSight(o.transform)) {
dist_closest = dist;
obj_closest = o;
}
}
return obj_closest;
}
bool InViewport(Vector3 worldPos) {
Vector3 p = cam.WorldToViewportPoint(worldPos);
return (p.x > 0.0f && p.x <= 1.0f && p.y > 0.0f && p.y <= 1.0f
&& p.z > cam.nearClipPlane);
}
bool HasLineOfSight(Transform target) {
RaycastHit hit;
Vector3 dir = target.position - transform.position;
if (Physics.Raycast(transform.position, dir, out hit, maxDistance)) {
if (hit.collider.gameObject == target.gameObject) {
return true;
}
}
return false;
}
}
Side notes:
Another issue with this technique is, that there can be tagged objects right in front of the camera, but other tagged objects that are closer on the side will be picked up instead of the obvious one. Many small issues to fine-tune until the scripts fits the game, I guess. Instead of only using one Raycast per object, you could use multiple ones, and take the bounding box or the actual collider shape into account.
An improved version of the script could make use of the Physics.Overlap*() or Physics.*Cast*() functions, documented here.
What I am trying to achieve is when my prefabs instantiate in my spawn area when they collide then one either moves from another or is destroyed and another spawn replaces it. I tried to use tags to get the other prefab touching. I tried getting the names' prefabs. I don't know what I am doing wrong. I did just drag my game object into the prefabs folder to get prefabs. Heres my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnArea : MonoBehaviour
{
int counter = 0;
public int max;
//public GameObject objects;
public GameObject[] objects;
public GameObject[] objectsPrefabs;
public Vector3 size;
public Vector3 center;
int xRotation = 0;
// Start is called before the first frame update
void Start()
{
Spawn();
}
// Update is called once per frame
void Update()
{
if (counter < max)
{
Spawn();
}
}
//void Spawn()
//{
// Vector3 pos = center + new Vector3(Random.Range(-size.x / 2, size.x / 2), Random.Range(-size.y / 2, size.y / 2), Random.Range(-size.z / 2, size.z / 2));
// Instantiate(objects, pos, Quaternion.Euler(0, xRotation, 0));
// xRotation += 45;
// counter++;
//}
void Spawn()
{
objects = new GameObject[objectsPrefabs.Length];
Vector3 pos = center + new Vector3(Random.Range(-size.x / 2, size.x / 2), Random.Range(-size.y / 2, size.y / 2), Random.Range(-size.z / 2, size.z / 2));
for (int i = 0; i < objectsPrefabs.Length; i++)
{
objects[i] = Instantiate(objectsPrefabs[i], pos, Quaternion.Euler(0, xRotation, 0)) as GameObject;
}
xRotation += 45;
counter++;
}
void OnCollisionEnter(Collision collision)
{
for (int i = 0; i < objectsPrefabs.Length; i++)
{
if (collision.transform.CompareTag("spawnwall"))
{
//if (objects[i].gameObject)
//{
Destroy(objectsPrefabs[i]);
counter--;
Spawn();
//}
}
}
}
private void OnDrawGizmosSelected()
{
Gizmos.color = new Color(1, 0, 0, 0.5f);
Gizmos.DrawCube(center, size);
}
}
According to the docs on collision, you must refer to collision.gameObject in order to refer to the other object the collision is referring to. Right now you are comparing the spawnwall tag against the tag of the game object this component belongs to.
When posing the questions, it would also be nice to know the following:
1. The desired output
2. The current symptoms
I also have the following concerns:
1. Are you sure your class members are initialized with the correct data? It seems to me that they are all either starting with C# default values.
2. Do you want the objects inside the area to do what you described when they (a) touch each other or (b) when they touch the area boundaries.
The way your current code is written makes me thinks that you have a bunch of objects inside a rectangular area. Then, when the objects collide with the boundaries of the rectangular area, they should be destroyed.
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);
}
I'm new to UnityScript and I have the following code that does a forward movement of a gameObject on "Z" axis, but needs some refinement. Let me explain.
The script runs when a GUI.Button is clicked. The gameObject starts moving...till infinity.
I have tried to make it move till a desired pos, (e.g. an empty gameObject pos) but didn't work at all.
How should I refine this code snippet to move the gameObject to a desired position on a first GUI.Button click and return to starting position on back click?
Furthermore, is it possible to have this movement made step by step on same GUI.Button clicks?
Here is the code snippet:
#pragma strict
// member variables (declared outside any function)
var startPos: Vector3;
var endPos : Vector3;
var cachedTransform : Transform;
private static var isforward = false;
// save pos before moving:
startPos = transform.position;
// make the gameObject transform, then restore the initial position when needed:
transform.position = startPos;
function Awake() {
startPos = transform.localPosition;
}
function Start() {
cachedTransform = transform;
startPos = cachedTransform.position;
}
function FixedUpdate() {
if(isforward){
var translation : float;
if (cachedTransform.position.x == endPos)
{
cachedTransform.position = startPos;
}
else
{
translation = Time.deltaTime * 2;
cachedTransform.Translate(0, 0, translation);
cachedTransform.Translate(Vector3.forward * translation);
}
}
}
static function doforward ()
{
isforward = !isforward;
}
Thank you all in advance for your answers.
You can easily move a game object if you attach a script to it, then (in JavaScript)
#pragma strict
var startPosition;
// Record the starting position when the scene loads
function Start () {
startPosition = gameObject.transform.position;
}
// Call this to move you object to wherever
function moveObject () {
var newPos = new Vector3 (10,20,0); //(where ever you need it to go)
gameObject.transform.position = newPos;
}
// Call this to move the object to starting position, using variable we made at start
function moveToStart () {
gameObject.transform.position = startPosition;
}
Then you just call those functions when you need to move the object around.
You might want to look into the Vector3.Lerp method. This takes two vectors (points) and a float as parameters, then gives you back a point that's a fraction of the way between them. So for example, Lerp(from, to, 0.3f) will give you a point 30% of the way between the two points. Then once you have this, all you need to do is set your object's transform.
I created a camera with a matrix and used it to move the view point in 2D. Basically I started from this template:
http://torshall.se/?p=272
I also had in one of my class, a simple code to spawn boxs with the mouse:
public void CreateBodies()
{
mouse = Mouse.GetState();
if (mouse.RightButton == ButtonState.Pressed)
{
Bodies += 1;
if (Bodies >= MaxBodies)
Bodies = 0;
rectBody[Bodies] = BodyFactory.CreateRectangle(world, ConvertUnits.ToSimUnits(rectangle.Width), ConvertUnits.ToSimUnits(rectangle.Height), 1);
rectBody[Bodies].Position = ConvertUnits.ToSimUnits(mouse.X, mouse.Y);
rectBody[Bodies].BodyType = BodyType.Dynamic;
}
}
This Worked perfectly fine but when I moved the ''camera'' the mouse didn't change in the right location, Si I did this little modification in game1.cs and in my method to have the world coord. of my mouse:
mouse = Mouse.GetState();
Matrix inverse = Matrix.Invert(camera.transform);
Vector2 mousePos = Vector2.Transform(new Vector2(mouse.X, mouse.Y), inverse);
TE.CreateBodies(mousePos);
public void CreateBodies(Vector2 mousePosition)
{
mouse = Mouse.GetState();
MousePosition = mousePosition;
if (mouse.RightButton == ButtonState.Pressed)
{
Bodies += 1;
if (Bodies >= MaxBodies)
{
Bodies = 0;
}
rectBody[Bodies] = BodyFactory.CreateRectangle(world, ConvertUnits.ToSimUnits(rectangle.Width), ConvertUnits.ToSimUnits(rectangle.Height), 1);
rectBody[Bodies].BodyType = BodyType.Dynamic;
rectBody[Bodies].Position = ConvertUnits.ToSimUnits(MousePosition);
}
}
Now this is supposed to give me the world coords. of my mouse, but I have a problem, when I run the program and click somewhere on the screen to create a box I get this error:
http://img68.xooimage.com/files/6/a/4/bob-2c526f4.png
What's going on? :/
Edit:
This is at the line 439 of body.cs:
Debug.Assert(!float.IsNaN(value.X) && !float.IsNaN(value.Y));