2

我的 2D 平台游戏关卡在地图上放置了宝箱,当收集到宝箱时,我需要显示一条消息。消息包含在一个List<string>并且随着宝物的收集,一一展示。这些消息将显示在 UI>Text 游戏对象中,该游戏对象锚定在画布的顶部中心。我想通过更新这个游戏对象的文本组件,在收集宝藏时将这些文本显示为浮动(淡入/淡出)。但是,如果在前一个的动画完成之前收集了两个或多个宝物,就会出现问题。我可以轻松地将新消息连接到现有消息,但我希望旧消息淡出,新消息淡入。这可以通过创建多个 UI>Texts 来完成,但是有很多消息,我没有想要创建这么多冗余的游戏对象。这个问题有什么好的解决方法吗? 在此处输入图像描述

4

2 回答 2

2

我在我的一个项目中处理这个问题的方式是创建一个要显示的消息队列(因为即时性不是问题,但一次只能显示一个是)。这听起来与您自己的问题非常相似。

// NotificationItem is just a wrapper around some text and accompanying image
private static List<NotificationItem> notificationQueue = new List<NotificationItem>();

// reference to the on-screen object
public GameObject notification;

// "Hey! I want to display a notification!"
public static void ShowNotification(NotificationItem item) {
    notificationQueue.Add(item);
}

// I was using the DO Tween asset here, but the logic can be converted to
// coroutines or straight update cycles
private void Update() {
    // If there is no currently displayed notification (ie the notification object is
    // not being animated) and there is at least one item to display
    if(!DOTween.IsTweening(notification.transform) && notificationQueue.Count > 0) {
        // ...get the first one
        NotificationItem item = notificationQueue[0];
        // ...pop it from the list
        notificationQueue.RemoveAt(0);
        // ...set the notification object to the details
        notification.transform.Find("Title").GetComponent<Text>().text = item.title;
        notification.transform.Find("Text").GetComponent<Text>().text = item.text;
        notification.transform.Find("Img").GetComponent<Image>().sprite = item.image;

        // ...start the animation
        // (in my case, the notification animates down from the top of the screen
        // waits 2.5 seconds, then animates back up)
        notification.transform.DOMoveY(Screen.height - 85, 0.5f, false).SetEase(Ease.InOutQuad).OnComplete(PauseCallback);
    }
}

// An admittedly hacky way of getting the notification to do nothing for 2.5 seconds:
// Animate it to where it already is.
private void PauseCallback() {
    notification.transform.DOMoveY(Screen.height - 85, 2.5f, false).SetEase(Ease.InOutQuad).OnComplete(ReturnCallback);
}

private void ReturnCallback() {
    notification.transform.DOMoveY(Screen.height + 2, 0.5f, false).SetEase(Ease.InOutQuad);
}

我的实现和您的实现之间的区别主要在于动画(以及您的 Queue 列表的类型;例如,您可能只使用 a List<string>)。您已经对动画进行了编码,您所需要的只是队列和一种确定动画是否完整的方法。

于 2018-07-27T21:28:40.207 回答
1

如果您使用享元模式(对象池),您将不会生成超过系统处理能力的对象。Unity在他们的网站上有一个对象池教程。

于 2018-07-27T19:40:40.320 回答