0

我有一个问题,我一直试图找出几个说,我似乎无法确定它的原因!我创建了一个第一人称射击游戏,它在一张小地图上由几个敌人组成。我有两个场景(主菜单和游戏关卡)。当我的玩家死亡时,它会进入主菜单,您可以从中选择再次玩游戏。然后再次重新加载关卡。第一次运行游戏时,它运行没有任何问题。但是,当我这样做并再次按下播放游戏按钮时,它会向我返回一条消息,其中指出以下内容“MissingReferenceException:'GameObject' 类型的对象已被破坏,但您仍在尝试访问它。” 从下面的代码中,我只能看到两种类型的 GameObject。我试图移除 muzzleFlash 以查看这是否是问题,但它没有任何区别。当我读到这可能是问题的原因时,我已经取消了所有静态框,但这并没有解决问题。下面的这个脚本附加到一个敌人,我有一个附加到 FPS 的 PlayerShot 脚本。请问有人可以帮忙吗?

// speed of the AI player
public var speed:int = 5;

// speed the ai player rotates by
public var rotationSpeed:int = 3;

// the waypoints
public var waypoints:Transform[];

// current waypoint id
private var waypointId:int = 0;

// the player
public var player:GameObject;

// firing toggle
private var firing:boolean = false;

// the Mesh Renderer of the Muzzle Flash GameObject
private var muzzleFlashAgent:GameObject;


/**
    Start
*/
function Start() 
{
    // retrieve the player
    player = GameObject.Find("First Person Controller");

    // retrieve the muzzle flash
    muzzleFlashAgent = GameObject.Find("muzzleFlashAgent");

    // disable the muzzle flash renderer
    muzzleFlashAgent.active = false;
}

/**
    Patrol around the waypoints
*/
function Patrol()
{
    // if no waypoints have been assigned
    if (waypoints.Length == 0) 
    {
        print("You need to assign some waypoints within the Inspector");
        return;
    }

    // if distance to waypoint is less than 2 metres then start heading toward next waypoint
    if (Vector3.Distance(waypoints[waypointId].position, transform.position) < 2)
    {
        // increase waypoint id
        waypointId++;

        // make sure new waypointId isn't greater than number of waypoints
        // if it is then set waypointId to 0 to head towards first waypoint again
        if (waypointId >= waypoints.Length) waypointId = 0;
    }

    // move towards the current waypointId's position
    MoveTowards(waypoints[waypointId].position);
}

/**
    Move towards the targetPosition
*/
function MoveTowards(targetPosition:Vector3)
{
    // calculate the direction
    var direction:Vector3 = targetPosition - transform.position;

    // rotate over time to face the target rotation - Quaternion.LookRotation(direction)
    transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);

    // set the x and z axis of rotation to 0 so the soldier stands upright (otherwise equals REALLY bad leaning)
    transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);

    // use the CharacterController Component's SimpleMove(...) function
    // multiply the soldiers forward vector by the speed to move the AI
    GetComponent (CharacterController).SimpleMove(transform.forward * speed);

    // play the walking animation
    animation.Play("walk");
}


/**
    Update
*/
function Update()
{
    // calculate the distance to the player
    var distanceToPlayer:int = Vector3.Distance(transform.position, player.transform.position);

    // calculate vector direction to the player
    var directionToPlayer:Vector3 = transform.position - player.transform.position;

    // calculate the angle between AI forward vector and direction toward player
    // we use Mathf.Abs to store the absolute value (i.e. always positive)
    var angle:int = Mathf.Abs(Vector3.Angle(transform.forward, directionToPlayer));

    // if player is within 30m and angle is greater than 130 (IN FRONT) then begin chasing the player
    if (distanceToPlayer < 30 && angle > 130)
    {
        // move towards the players position
        MoveTowards(player.transform.position);

        // if not firing then start firing!
        if (!firing) Fire();
    }
    // if player is within 5m and BEHIND then begin chasing
    else if (distanceToPlayer < 5 && angle < 130)
    {
        // move towards the players position
        MoveTowards(player.transform.position);

        // if not firing then start firing!
        if (!firing) Fire();
    }
    else
    {
        // patrol
        Patrol(); 

        // stop firing
        firing = false;
    }
}

/**
    Fire at the player
*/
function Fire()
{
    // toggle firing on
    firing = true;

    // check if still firing
    while (firing)
    {
        // hit variable for RayCasting
        var hit:RaycastHit;

        // range of weapon
        var range:int = 30;

        // fire the ray from our position of our muzzle flash, forwards "range" metres and store whatever is detected in the variable "hit"
        if (Physics.Raycast(muzzleFlashAgent.transform.position, transform.forward, hit, range)) 
        {
            // draw a line in the scene so we can see what's going on
            Debug.DrawLine (muzzleFlashAgent.transform.position, hit.point);

            // if we hit the player
            if (hit.transform.name == "First Person Controller")
            {
                // inform the player that they have been shot
                player.GetComponent(PlayerShot).Shot();  

                // play gunshot sound
                audio.PlayOneShot(audio.clip);


                // show muzzle flash for X seconds
                muzzleFlashAgent.active = true;
                yield WaitForSeconds(0.05);
                muzzleFlashAgent.active = false; 

                // wait a second or two before firing again
                yield WaitForSeconds(Random.Range(1.0, 2.0));
            }
        }

        // wait till next frame to test again
        yield;
    }
}

这是破坏游戏对象的 PlayerShot。

// the sound to play when the player is shot
public var shotSound:AudioClip;



// the number of lives
public var lives:int = 3;


/**
    Player has been shot
*/
function Shot () 
{
    // play the shot audio clip
    audio.PlayOneShot(shotSound);

    // reduce lives
    lives--;

    // reload the level if no lives left
    if (lives == 0)
    {
        // destroy the crosshair
        Destroy(GetComponent(CrossHair));


        // add the camera fade (black by default)
        iTween.CameraFadeAdd();

        // fade the transparency to 1 over 1 second and reload scene once complete
        iTween.CameraFadeTo(iTween.Hash("amount", 1, "time", 1, "oncomplete", "ReloadScene", "oncompletetarget", gameObject));
    }
}


/**
    Reload the scene
*/ 
function ReloadScene()
{
    // reload scene
    Application.LoadLevel("MainMenu");
}

与 BasicAI 一起附加到敌人的脚本是用于破坏游戏对象的 SoldierShot 脚本。下面是脚本。

public var ragdoll:GameObject;

/**
    Function called to kill the soldier
*/
function Shot()
{
    // instantiate the ragdoll at this transform's position and rotation
    Instantiate(ragdoll, transform.position, transform.rotation);

    Destroy(GetComponent(BasicAI));
    // destroy the animated soldier gameobject
    Destroy(gameObject);

}
4

2 回答 2

2

似乎您保留了对被破坏的 GameObject 的引用(或者我错了吗?)。

与常见的 C#(可能还有 javascript)程序中发生的情况相反,当您引用一个对象时,它永远不会被垃圾收集,在 Unity 中,如果您销毁该对象,您对它的所有引用都将转到null.

于 2012-04-19T03:16:37.730 回答
1

轻松修复,您可以删除“游戏关卡”中的游戏对象,并使用以下命令即时实例化您的士兵:

var instance : GameObject = Instantiate(Resources.Load("Soldier"));

您只需要在项目文件夹中创建一个资源文件夹,然后将焊接的预制件放入其中。

于 2012-07-19T03:46:15.253 回答