重播系统,环形缓冲区,在达到帧缓冲区之前开始重播

时间:2016-06-01 16:46:06

标签: c# unity3d

我有一个重播系统,用于我在Unity制作的游戏。它存储在keyFrame数组中的帧的帧缓冲区,并在帧超过帧缓冲区后替换帧。如果按任何" Fire1"纽扣。如果存储的帧数比帧缓冲区多,则重放效果很好,但是当存储的帧数少于帧缓冲区时,它会重放并停止,当它到达空帧时没有任何移动因为没有#39 ; t足够的帧(What's Happening GIF

using UnityEngine;
using System.Collections;

public class ReplaySystem : MonoBehaviour
{
    private const int bufferFrames = 500;
    private MyKeyFrame[] keyFrames = new MyKeyFrame[bufferFrames];
    private Rigidbody rigidBody;

    // Use this for initialization
    void Start()
    {
        rigidBody = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetButton("Fire1"))
            PlayBack();
        else
            Record();
    }

    private void PlayBack()
    {
        rigidBody.isKinematic = true;
        int frame = Time.frameCount % bufferFrames;
        Debug.Log("Reading frame " + frame);
        transform.position = keyFrames[frame].pos;
        transform.rotation = keyFrames[frame].rot;

    }

    private void Record()
    {
        rigidBody.isKinematic = false;
        int frame = Time.frameCount % bufferFrames;
        float time = Time.time;
        Debug.Log("Writing frame " + frame);

        keyFrames[frame] = new MyKeyFrame(time, transform.position, transform.rotation);
    }
}
/// <summary>
/// A Structure for storing time, position, and rotation
/// </summary>
public struct MyKeyFrame
{
    public float frameTime;
    public Vector3 pos;
    public Quaternion rot;

    public MyKeyFrame(float time, Vector3 pos, Quaternion rot)
    {
        frameTime = time;
        this.pos = pos;
        this.rot = rot;
    }
}

如果存储的帧数少于帧缓冲区,如何从存储的关键帧数量开始播放PlayBack?

我已尝试过的内容:   - 计算存储的关键帧数量   - 从Time.frameCount中减去bufferFrame,然后获得模数

1 个答案:

答案 0 :(得分:0)

我的解决方案。可能需要更多调整。

using UnityEngine;

使用System.Collections;

public class ReplaySystem:MonoBehaviour {

private const int bufferFrames = 1000;
private MyKeyFrame[] keyFrames = new MyKeyFrame[bufferFrames];
private Rigidbody rigidBody;
private GameManager gameManager;

private bool bufferArrayFull = false;
private bool setBufferCount = false;
private int bufferCountOnClick;

// Use this for initialization
void Start () {
    rigidBody = GetComponent<Rigidbody>();
    gameManager = GameObject.FindObjectOfType<GameManager>();
}

// Update is called once per frame
void Update () {

    if (gameManager.recording){
        Record();
    } else {
        Playback();
    }
}

void Playback (){
    rigidBody.isKinematic = true;
    int frame = Time.frameCount % bufferFrames;

    if (!bufferArrayFull && !setBufferCount){
        bufferCountOnClick = frame;
        setBufferCount = true;
    } else if (!bufferArrayFull && setBufferCount){
        int newFrame = frame - bufferCountOnClick;
        frame = newFrame;
    }
    Debug.Log("Playback frame " + frame + " current frameCOunt is " + Time.frameCount);
    transform.position = keyFrames[frame].position;
    transform.rotation = keyFrames[frame].rotation;
}

void Record ()
{
    rigidBody.isKinematic = false;
    float time = Time.time;
    int frame = Time.frameCount % bufferFrames;

    if (frame == bufferFrames-1 && !bufferArrayFull){
        bufferArrayFull = true;
        print ("Buffer is full");
    }

    Debug.Log("Recording frame " + frame + " current frameCOunt is " + Time.frameCount);
    keyFrames [frame] = new MyKeyFrame (time, transform.position, transform.rotation);
}

}

public struct MyKeyFrame {

public float frameTime;
public Vector3 position;
public Quaternion rotation;

public MyKeyFrame (float aTime, Vector3 aPosition, Quaternion aRotation){
    frameTime = aTime;
    position = aPosition;
    rotation = aRotation;
} 

}