我如何同时使用两个脚本航路点和传送,以及如何使传送更好地工作?

问题描述 投票:0回答:1

在Waypoint脚本中,脚本已附加到角色。角色等待10秒,然后进入步行状态并开始在航点之间移动。在最后一个航路点,角色进入空闲状态。

using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.AI;

public class Waypoints : UnityEngine.MonoBehaviour
{
    public List<GameObject> waypoints = new List<GameObject>();
    public Animator _animator;
    public int waitTimeBeforeGo;
    public int num = 0;
    public float minDist;
    public float speed;
    public bool rand = false;
    public bool go = true;
    public bool loop = false;
    public bool waitTime = false;
    public float smoothRotation;
    public bool inIdle = false;

    private bool lastPoint = false;

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        float dist = Vector3.Distance(gameObject.transform.position, waypoints[num].transform.position);

        if (waitTime == true)
        {
            StartCoroutine(WaitBeforeGo());
        }
        else
        {
            if (go)
            {
                _animator.SetBool("Walk", true);

                if (dist > minDist && lastPoint == false)
                {
                    Move();
                }
                else
                {
                    if (!rand)
                    {
                        if (num + 1 == waypoints.Count)
                        {
                            if (loop == true)
                            {
                                num = 0;
                            }

                            lastPoint = true;
                            _animator.SetBool("Idle", true);
                            inIdle = true;
                        }
                        else
                        {
                            num++;
                        }
                    }
                    else
                    {
                        num = Random.Range(0, waypoints.Count);
                    }
                }
            }
        }
    }

    public void Move()
    {
        Quaternion lookOnLook =
 Quaternion.LookRotation(waypoints[num].transform.position - transform.position);

        transform.rotation =
        Quaternion.Slerp(transform.rotation, lookOnLook, Time.deltaTime * smoothRotation);

        gameObject.transform.position += gameObject.transform.forward * speed * Time.deltaTime;
    }

    IEnumerator WaitBeforeGo()
    {
        yield return new WaitForSeconds(waitTimeBeforeGo);

        waitTime = false;
    }
}

现在,我还有一个附加在传送对象上的传送脚本。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class Teleporting : MonoBehaviour
{
    public List<GameObject> teleporters = new List<GameObject>();
    public GameObject objectToTeleportMaterial;
    public Waypoints waypoints;
    public float fadeDuration = 5;
    public float fadeInTargetOpacity = 0;
    public float fadeOutTargetOpacity = 1;

    private List<Vector3> teleportersPositions = new List<Vector3>();
    private bool teleported = false;
    private Material material;
    private GameObject myother;


    // Start is called before the first frame update
    void Start()
    {

    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.name == "vanguard_t_choonyung@T-Pose (1)")
        {
            teleported = false;
            myother = other.gameObject;
            material = objectToTeleportMaterial.GetComponent<Renderer>().material;
            Teleport(material, fadeInTargetOpacity, fadeDuration);
        }
    }

    // Update is called once per frame
    void Update()
    {
        if(waypoints.inIdle == true)
        {   
            material.ToTransparentMode();
        }

        if (teleported == true)
        {
            myother.transform.position = teleporters[1].transform.position;
            Teleport(material, fadeOutTargetOpacity, fadeDuration);
            material.ToOpaqueMode();
            teleported = false;
        }
    }

    private void Teleport(Material material, float fadeTargetOpacity, float fadeDuration)
    {
        StartCoroutine(FadeTo(material, fadeTargetOpacity, fadeDuration));
    }

    // Define an enumerator to perform our fading.
    // Pass it the material to fade, the opacity to fade to (0 = transparent, 1 = opaque),
    // and the number of seconds to fade over.
    IEnumerator FadeTo(Material material, float targetOpacity, float duration)
    {

        // Cache the current color of the material, and its initiql opacity.
        Color color = material.color;
        float startOpacity = color.a;

        // Track how many seconds we've been fading.
        float t = 0;

        while (t < duration)
        {
            // Step the fade forward one frame.
            t += Time.deltaTime;
            // Turn the time into an interpolation factor between 0 and 1.
            float blend = Mathf.Clamp01(t / duration);

            // Blend to the corresponding opacity between start & target.
            color.a = Mathf.Lerp(startOpacity, targetOpacity, blend);

            // Apply the resulting color to the material.
            material.color = color;

            // Wait one frame, and repeat.
            yield return null;
        }

        if (targetOpacity == 1)
        {

        }

        if (targetOpacity == 0)
        {
            teleported = true;
        }
    }
}

使用此脚本,我遇到了一些问题。

  • 在开始传送时角色会在材质设置中更改为透明模式,但是在将其传送到新位置后又将其传送到新位置后,他再也不会在材质设置中变回不透明模式。

  • 在新位置上,当角色开始向后渐退一毫秒时,角色会像在不透明模式下那样显示,但随后他消失了,然后在第二个传送器中开始渐入,但是从不更改为不透明模式。

此类是用于在“透明”和“不透明”之间更改材料模式的辅助类:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class MaterialExtensions
{
    public static void ToOpaqueMode(this Material material)
    {
        material.SetOverrideTag("RenderType", "");
        material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
        material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
        material.SetInt("_ZWrite", 1);
        material.DisableKeyword("_ALPHATEST_ON");
        material.DisableKeyword("_ALPHABLEND_ON");
        material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
        material.renderQueue = -1;
    }

    public static void ToTransparentMode(this Material material)
    {
        material.SetOverrideTag("RenderType", "Transparent");
        material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
        material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
        material.SetInt("_ZWrite", 0);
        material.DisableKeyword("_ALPHATEST_ON");
        material.EnableKeyword("_ALPHABLEND_ON");
        material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
        material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
    }
}

我想做什么:

  • 角色在航点之间行走。当角色到达最后一个航路点并进入空闲状态时,请等待1-2秒,然后再开始传送。

  • [开始传送时,角色应更改为透明模式并逐渐淡出并更改位置。

  • 在新位置,角色应缓慢淡入,然后慢慢变回不透明模式。

  • 角色应该在传送消失后并在变回不透明模式后开始在其新位置的新航路点之间移动。

如何使角色在空闲状态下等待1-2秒才能开始传送?

在淡入以及更改为不透明模式以开始在新航路点之间移动后,如何使角色在他的新位置上?我在他的新位置添加了航路点。

我该如何解决传送脚本的问题?自身的瞬移仍然不流畅。第一次淡出部分很好,但是新位置的淡入效果不好。

一些有关透明和不透明模式的屏幕截图。

[当Alpha值设置为255时,在透明模式下显示Alpha的第一张屏幕截图:

即使在透明模式下,alpha值为255,字符仍然看起来是透明的。

Transparent alpha color is set to 255

这次第二张屏幕截图也透明al [ha设置为0:

Transparent mode alpha is set to 0 but still some of the character still show

我现在看到,即使在alpha为0的“透明”上,您也可以看到他尚未消失的角色的一小部分仍然留在他身边。

现在是不透明模式的屏幕截图,因为如果不透明模式下的alpha为0或255,则什么都不会改变:

Opaque mode alpha is at 255

所以到目前为止,我从此屏幕快照和模式中学到了什么:

  1. 当alpha设置为0时,透明模式不会使字符完全消失。看起来好像距离有点远,但是如果看起来很近,您会看到仍然有一些字符。

  2. 透明模式,当alpha设置为255时,字符没有完全填满,他看起来仍然是透明的。

  3. 不透明模式,当alpha设置为0或255时,相同的结果使字符像原始字符一样被填充。

我在标准着色器上所做的所有这些测试。

c# unity3d
1个回答
0
投票

透明度问题

您使用自定义着色器吗?因为我认为更简单的解决方案是将材质与标准着色器一起使用,所以可以设置Rendering Mode。然后,您不必处理着色器中的设置属性。有一种专门用于淡入和淡出(BlendMode.Fade

的模式

[我相信,如果您将材质设置为能够透明的材质,则不会真正改变效果(也许在性能上会有所提高,但不会太大),alpha仍然为不透明,因此在视觉上不会有所不同。

如果您仍然想在透明和不透明渲染模式之间切换或使用扩展方法,我建议在协程完成后将开关切换到不透明模式:

if(targetOpacity == 1f) { material.ToOpaqueMode(); }

并且不是立即启动协程后的。

x秒后传送

您可以编写另一个协程/函数,在x秒后调用一个函数

仅使用协程

private IEnumerator TeleportAfter(float time, etc...) {
    yield return new WaitForSeconds(time);
    Teleport(...);
}

使用协程和包装函数(更易于调用/不需要StartCoroutine *]]

private IEnumerator TeleportAfter(float time, etc...) {
    yield return new WaitForSeconds(time);
    Teleport(...);
}

private void TeleportAfterSeconds(float time, etc...) {
    StartCoroutine(TeleportAfter(time, etc...));
}
    
© www.soinside.com 2019 - 2024. All rights reserved.