You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity星露谷物语风格钓鱼小游戏脚本问题:鱼与钩子异常

问题与修复方案

问题概述

我正在制作一款类似《星露谷物语》(Stardew Valley)钓鱼机制的小游戏,设置了两个空对象作为边界,用于限制鱼和钩子在矩形区域内。运行脚本时遇到两个问题:

  • 鱼并非从预设初始位置开始移动,而是直接从底部边界生成并向上移动
  • 钩子固定在底部边界,用户点击鼠标时完全没有移动反应

原代码

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

public class FishingMiniGame : MonoBehaviour
{
    //Make the Egg move
    [Header("Fishing Area")]
    [SerializeField] Transform topBounds;
    [SerializeField] Transform bottomBounds;

    [Header("Fish Settings")]
    [SerializeField] Transform Fish;
    [SerializeField] float smoothMotion = 3f;
    [SerializeField] float fishTimeRandomizer = 3f;
    float fishPosition;
    float fishSpeed;
    float fishTimer;
    float fishTargetPosition;

    [Header("Hook Settinds")]
    [SerializeField] Transform Hook;
    [SerializeField] float HookSize = .18f;
    [SerializeField] float HookSpeed = .1f;
    [SerializeField] float HookGravity = .05f;
    float hookPosition;
    float hookPullVelocity;

    private void FixedUpdate()
    {
        MoveFish();
        MoveHook();
    }

    private void MoveHook()
    {
        if(Input.GetMouseButtonDown(0))
        {
            //increase our pull velocity
            hookPullVelocity += HookSpeed * Time.deltaTime; //raises out hook
        }
        hookPullVelocity -= HookGravity * Time.deltaTime;

        hookPosition += hookPullVelocity;
        hookPosition = Mathf.Clamp(hookPosition, 0, 1); //keep the jook withon bounds
        Hook.position = Vector3.Lerp(bottomBounds.position, topBounds.position, hookPosition);
    }

    private void MoveFish()
    {
        //based on timer, pick random position
        //move fish to that position smoothly
        fishTimer -= Time.deltaTime;
        if(fishTimer < 0)
        {
            //pick a new target position
            //reset timer
            fishTimer = Random.value * fishTimeRandomizer;
            fishTargetPosition = Random.value;
        }

        fishPosition = Mathf.SmoothDamp(fishPosition, fishTargetPosition, ref fishSpeed, smoothMotion);
        Fish.position = Vector3.Lerp(bottomBounds, topBounds, fishPosition);

    }
}

问题分析与修复

1. 鱼的初始位置异常问题

  • 原因:
    • fishTimer未初始化,脚本启动后默认值为0,会立刻触发随机目标位置逻辑,导致鱼直接从底部(fishPosition初始为0)开始移动
    • Vector3.Lerp参数错误:传入了bottomBounds(Transform组件)而非bottomBounds.position(世界坐标),虽Unity会隐式转换,但写法不规范
  • 修复:
    • 添加Start()方法初始化鱼的初始状态,让鱼先停在中间位置,再开始随机移动
    • 修正Vector3.Lerp的参数为位置坐标

2. 钩子无响应问题

  • 原因:
    • HookSpeed数值过小:0.1 * Time.deltaTime(约0.002)的增量远小于重力减量(0.05 * Time.deltaTime约0.001),点击产生的速度变化可忽略
    • Input.GetMouseButtonDown(0)在FixedUpdate中易漏检:FixedUpdate更新频率与Update不同,单次点击可能错过执行时机
  • 修复:
    • 调大HookSpeed至合适数值(比如5),让点击的速度增量明显超过重力
    • 改用Input.GetMouseButton(0)检测按住状态,确保持续输入时钩子能持续获得速度
    • 将输入检测移至Update()方法,避免漏检(Update每帧执行,更适合处理输入)

修复后的代码

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

public class FishingMiniGame : MonoBehaviour
{
    [Header("Fishing Area")]
    [SerializeField] Transform topBounds;
    [SerializeField] Transform bottomBounds;

    [Header("Fish Settings")]
    [SerializeField] Transform Fish;
    [SerializeField] float smoothMotion = 3f;
    [SerializeField] float fishTimeRandomizer = 3f;
    float fishPosition;
    float fishSpeed;
    float fishTimer;
    float fishTargetPosition;

    [Header("Hook Settings")] // 修正拼写错误
    [SerializeField] Transform Hook;
    [SerializeField] float HookSize = .18f;
    [SerializeField] float HookSpeed = 5f; // 调大速度值
    [SerializeField] float HookGravity = .05f;
    float hookPosition;
    float hookPullVelocity;
    private bool isPulling; // 传递输入状态

    private void Start()
    {
        // 初始化鱼的初始位置和计时器
        float midY = (bottomBounds.position.y + topBounds.position.y) / 2f;
        fishPosition = (midY - bottomBounds.position.y) / (topBounds.position.y - bottomBounds.position.y);
        fishTargetPosition = fishPosition;
        fishTimer = Random.value * fishTimeRandomizer;
        // 初始化钩子位置
        hookPosition = 0;
        Hook.position = bottomBounds.position;
    }

    private void Update()
    {
        // 在Update中处理输入,避免漏检
        isPulling = Input.GetMouseButton(0);
    }

    private void FixedUpdate()
    {
        MoveFish();
        MoveHook();
    }

    private void MoveHook()
    {
        if(isPulling)
        {
            // 按住时持续增加拉力速度
            hookPullVelocity += HookSpeed * Time.deltaTime;
        }
        hookPullVelocity -= HookGravity * Time.deltaTime;
        // 限制速度,避免钩子移动过快
        hookPullVelocity = Mathf.Clamp(hookPullVelocity, -2f, 2f);

        hookPosition += hookPullVelocity;
        hookPosition = Mathf.Clamp(hookPosition, 0, 1);
        Hook.position = Vector3.Lerp(bottomBounds.position, topBounds.position, hookPosition);
    }

    private void MoveFish()
    {
        fishTimer -= Time.deltaTime;
        if(fishTimer < 0)
        {
            fishTimer = Random.value * fishTimeRandomizer;
            fishTargetPosition = Random.value;
        }

        fishPosition = Mathf.SmoothDamp(fishPosition, fishTargetPosition, ref fishSpeed, smoothMotion);
        // 修正Lerp参数为位置坐标
        Fish.position = Vector3.Lerp(bottomBounds.position, topBounds.position, fishPosition);
    }
}

额外优化点

  • 修正了原代码中Hook Settinds的拼写错误为Hook Settings
  • 添加了速度限制,防止钩子因持续点击导致速度过大
  • 将输入逻辑移至Update(),确保输入检测更可靠

内容的提问来源于stack exchange,提问作者MarcusLee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 02:55:24