u3d js 如何相互调用

可以!通过 webViewObject.EvaluateJS() 可以完全控制网页的列表。下面给你完整方案:

一、HTML页面结构

复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>列表管理</title>
    <style>
        .list-container {
            width: 100%;
            max-width: 600px;
            margin: 20px auto;
        }
        .list-item {
            padding: 10px;
            margin: 5px 0;
            background: #f0f0f0;
            border-radius: 5px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .delete-btn {
            background: #ff4444;
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 3px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="list-container">
        <h2>商品列表</h2>
        <ul id="productList"></ul>
    </div>

    <script>
        // 添加列表项
        function addItem(id, name, price) {
            var list = document.getElementById('productList');
            var li = document.createElement('li');
            li.className = 'list-item';
            li.id = 'item-' + id;
            li.innerHTML = `
                <div>
                    <strong>${name}</strong>
                    <span style="color: #666;"> - ¥${price}</span>
                </div>
                <button class="delete-btn" onclick="deleteItemAndNotify('${id}')">删除</button>
            `;
            list.appendChild(li);
            
            // 通知Unity添加成功
            Unity.call('itemAdded:' + id);
        }

        // 删除列表项
        function deleteItem(id) {
            var item = document.getElementById('item-' + id);
            if (item) {
                item.remove();
                return true;
            }
            return false;
        }

        // 删除并通知Unity
        function deleteItemAndNotify(id) {
            if (deleteItem(id)) {
                Unity.call('itemDeleted:' + id);
            }
        }

        // 修改列表项
        function updateItem(id, name, price) {
            var item = document.getElementById('item-' + id);
            if (item) {
                item.querySelector('div').innerHTML = `
                    <strong>${name}</strong>
                    <span style="color: #666;"> - ¥${price}</span>
                `;
                Unity.call('itemUpdated:' + id);
                return true;
            }
            return false;
        }

        // 清空列表
        function clearList() {
            document.getElementById('productList').innerHTML = '';
            Unity.call('listCleared');
        }

        // 批量添加
        function addItems(jsonArray) {
            var items = JSON.parse(jsonArray);
            items.forEach(function(item) {
                addItem(item.id, item.name, item.price);
            });
        }

        // 获取列表数据(返回给Unity)
        function getListData() {
            var list = document.getElementById('productList');
            var items = [];
            list.querySelectorAll('.list-item').forEach(function(li) {
                items.push({
                    id: li.id.replace('item-', ''),
                    name: li.querySelector('strong').textContent,
                    price: li.querySelector('span').textContent
                });
            });
            Unity.call('listData:' + JSON.stringify(items));
        }
    </script>
</body>
</html>

二、Unity C# 控制代码

复制代码
using UnityEngine;
using System.Collections.Generic;
using Newtonsoft.Json; // 或使用 JsonUtility

public class WebViewListController : MonoBehaviour
{
    private WebViewObject webViewObject;

    void Start()
    {
        // 初始化WebView(参考你的示例代码)
        InitWebView();
    }

    void InitWebView()
    {
        webViewObject = gameObject.AddComponent<WebViewObject>();
        webViewObject.Init(
            cb: (msg) =>
            {
                Debug.Log($"JS消息: {msg}");
                HandleJSMessage(msg);
            },
            ld: (msg) =>
            {
                Debug.Log("页面加载完成");
                // 页面加载后初始化数据
                InitListData();
            }
        );

        webViewObject.SetMargins(0, 0, 0, 0);
        webViewObject.SetVisibility(true);
        webViewObject.LoadURL("file://" + Application.streamingAssetsPath + "/list.html");
    }

    // 处理来自JS的消息
    void HandleJSMessage(string msg)
    {
        if (msg.StartsWith("itemAdded:"))
        {
            string id = msg.Replace("itemAdded:", "");
            Debug.Log($"商品 {id} 添加成功");
        }
        else if (msg.StartsWith("itemDeleted:"))
        {
            string id = msg.Replace("itemDeleted:", "");
            Debug.Log($"商品 {id} 已删除");
            OnItemDeleted(id);
        }
        else if (msg.StartsWith("listData:"))
        {
            string json = msg.Replace("listData:", "");
            Debug.Log($"列表数据: {json}");
        }
    }

    // ========== Unity调用JS:列表操作 ==========

    // 添加单个商品
    public void AddProduct(string id, string name, float price)
    {
        string js = $"addItem('{id}', '{EscapeJS(name)}', {price});";
        webViewObject?.EvaluateJS(js);
    }

    // 删除商品
    public void DeleteProduct(string id)
    {
        string js = $"deleteItem('{id}');";
        webViewObject?.EvaluateJS(js);
    }

    // 修改商品
    public void UpdateProduct(string id, string name, float price)
    {
        string js = $"updateItem('{id}', '{EscapeJS(name)}', {price});";
        webViewObject?.EvaluateJS(js);
    }

    // 清空列表
    public void ClearList()
    {
        string js = "clearList();";
        webViewObject?.EvaluateJS(js);
    }

    // 批量添加商品
    public void AddProductsBatch(List<Product> products)
    {
        string json = JsonConvert.SerializeObject(products);
        // JSON中的引号需要转义
        json = json.Replace("\"", "\\\"");
        string js = $"addItems(\"{json}\");";
        webViewObject?.EvaluateJS(js);
    }

    // 获取列表数据
    public void GetListData()
    {
        string js = "getListData();";
        webViewObject?.EvaluateJS(js);
    }

    // ========== 初始化数据示例 ==========
    void InitListData()
    {
        // 方式1:单个添加
        AddProduct("001", "iPhone 15", 5999);
        AddProduct("002", "iPad Pro", 6799);
        AddProduct("003", "MacBook Air", 9999);

        // 方式2:批量添加
        var products = new List<Product>
        {
            new Product { id = "004", name = "AirPods", price = 1299 },
            new Product { id = "005", name = "Apple Watch", price = 2999 }
        };
        // AddProductsBatch(products);
    }

    // 响应删除事件
    void OnItemDeleted(string id)
    {
        // 这里可以同步更新Unity的数据
        Debug.Log($"同步删除Unity数据: {id}");
    }

    // JS字符串转义
    string EscapeJS(string text)
    {
        return text.Replace("'", "\\'").Replace("\n", "\\n");
    }

    // ========== 测试按钮 ==========
    void OnGUI()
    {
        if (GUI.Button(new Rect(10, 10, 150, 50), "添加商品"))
        {
            AddProduct("999", "测试商品", 99.99f);
        }

        if (GUI.Button(new Rect(10, 70, 150, 50), "删除商品001"))
        {
            DeleteProduct("001");
        }

        if (GUI.Button(new Rect(10, 130, 150, 50), "修改商品002"))
        {
            UpdateProduct("002", "iPad Pro 2024", 7999);
        }

        if (GUI.Button(new Rect(10, 190, 150, 50), "清空列表"))
        {
            ClearList();
        }

        if (GUI.Button(new Rect(10, 250, 150, 50), "获取列表数据"))
        {
            GetListData();
        }
    }
}

// 商品数据类
[System.Serializable]
public class Product
{
    public string id;
    public string name;
    public float price;
}

三、高级用法:带动画效果

复制代码
// 添加商品(带动画)
function addItemWithAnimation(id, name, price) {
    var list = document.getElementById('productList');
    var li = document.createElement('li');
    li.className = 'list-item';
    li.id = 'item-' + id;
    li.style.opacity = '0';
    li.style.transform = 'translateX(-50px)';
    li.innerHTML = `
        <div>
            <strong>${name}</strong>
            <span style="color: #666;"> - ¥${price}</span>
        </div>
        <button class="delete-btn" onclick="deleteItemAndNotify('${id}')">删除</button>
    `;
    list.appendChild(li);
    
    // 动画效果
    setTimeout(function() {
        li.style.transition = 'all 0.3s ease';
        li.style.opacity = '1';
        li.style.transform = 'translateX(0)';
    }, 10);
    
    Unity.call('itemAdded:' + id);
}

// 删除商品(带动画)
function deleteItemWithAnimation(id) {
    var item = document.getElementById('item-' + id);
    if (item) {
        item.style.transition = 'all 0.3s ease';
        item.style.opacity = '0';
        item.style.transform = 'translateX(50px)';
        setTimeout(function() {
            item.remove();
        }, 300);
        return true;
    }
    return false;
}

四、实战场景示例

场景1:网络请求后更新列表

复制代码
async void LoadProductsFromServer()
{
    // 从服务器获取数据
    string json = await GetProductsFromAPI();
    var products = JsonConvert.DeserializeObject<List<Product>>(json);
    
    // 先清空列表
    ClearList();
    
    // 等待一帧确保清空完成
    await System.Threading.Tasks.Task.Delay(100);
    
    // 批量添加到网页
    AddProductsBatch(products);
}

场景2:搜索过滤列表

复制代码
// 在HTML中添加搜索功能
function filterList(keyword) {
    var items = document.querySelectorAll('.list-item');
    items.forEach(function(item) {
        var name = item.querySelector('strong').textContent;
        if (name.toLowerCase().includes(keyword.toLowerCase())) {
            item.style.display = 'flex';
        } else {
            item.style.display = 'none';
        }
    });
}

// Unity端调用搜索
public void SearchProducts(string keyword)
{
    string js = $"filterList('{EscapeJS(keyword)}');";
    webViewObject?.EvaluateJS(js);
}

场景3:列表项点击事件

复制代码
// 修改HTML,添加点击事件
li.onclick = function() {
    Unity.call('itemClicked:' + id);
};

// Unity处理点击
void HandleJSMessage(string msg)
{
    if (msg.StartsWith("itemClicked:"))
    {
        string id = msg.Replace("itemClicked:", "");
        ShowProductDetail(id);
    }
}

五、注意事项

  1. 字符串转义:传递包含特殊字符(引号、换行)的字符串时要转义

  2. 异步问题EvaluateJS 是异步的,连续调用可能需要延迟

  3. 性能优化:批量操作优于多次单个操作

  4. 错误处理:JS执行失败时Unity不会报错,需要JS端返回结果确认

    // 带确认的操作
    public void AddProductSafe(string id, string name, float price)
    {
    string js = $@"
    try {{
    addItem('{id}', '{EscapeJS(name)}', {price});
    Unity.call('success:add:{id}');
    }} catch(e) {{
    Unity.call('error:' + e.message);
    }}
    ";
    webViewObject?.EvaluateJS(js);
    }

相关推荐
mayzhengxi1 年前
Artistic Color Isolation 颜色隔离效果
unity·u3d·效果·资源
墨尊1 年前
无人机巡检小羊仿真
无人机·gazebo·u3d·mavlink·qgc
NueXini1 年前
灵感互娱U3D笔试题
面试·题目·笔试题·u3d·灵感互娱
Uqiumu2 年前
面试记录(被问倒的)
面试·职场和发展·u3d
迷牙2 年前
中国移动杭州公司——亚运会网络运行保障系统
unity·数字孪生·数据可视化·u3d